本帖最后由 xuezhezhao 于 2012-11-24 14:30:22 编辑

解决方案 »

  1.   

    如果你的代码所在的进程中有多个线程在同时运行,而这些线程可能会同时运行这段代码。如果每次运行结果和单线程运行的结果是一样的,而且其他的变量的值也和预期的是一样的,就是线程安全的。
     若每个线程中对全局变量、静态变量只有读操作,而无写操作,一般来说,这个全局变量是线程安全的;若有多个线程同时执行写操作,一般都需要考虑线程同步,否则就可能影响线程安全。
    上面的这些复制的。
    其实举一个简单例子,两个人同时操作两台ATM机,一个人往一个账号存钱,另一个取钱。
    存钱的获取原来的值为500,然后存入500,返回写入为1000,但是因为延迟还未写会,
    另一个速度快,提了500,返回应该为0,这时第一个再返回1000写入,这样等于结果还是1000.
    你那个程序我看了,已经加了sy锁了,应该就是线程安全的。
    去掉那个关键字,然后数据量调大一点,就会看到线程不安全的效果了。
      

  2.   

    这个要用到线程同步!
    比如自定义一个同步类:
    /**
     * 分子处理线程和数据库写入线程的同步信号量
     * @author Administrator
     *
     */
    public class MySemaphore {
    private int count; public MySemaphore(int n) {
    this.count = n;
    } public synchronized void acquire() {
    count--;
    if(count<0){
    try {
    wait();
    } catch (InterruptedException e) {
    // keep trying
    }
    }
    } public synchronized void release() {
    count++;
    if(count>=0) 
    notify(); // alert a thread that's blocking on this semaphore
    }
    }
      

  3.   

    syn = new MySemaphore(N)//定义一个同步信号量
    syn.acquire();//关锁
    syn.release()//开锁
      

  4.   

    用同一个锁就行 Lock()
    看看“毕向东”的JavaSE
      

  5.   


    class Resource
    {
    private String name;
    private int count = 1;
    private boolean flag = false;// 创建一个锁对象。
    Lock lock = new ReentrantLock(); //通过已有的锁获取该锁上的监视器对象。
    // Condition con = lock.newCondition(); //通过已有的锁获取两组监视器,一组监视生产者,一组监视消费者。
    Condition producer_con = lock.newCondition();
    Condition consumer_con = lock.newCondition();
    public  void set(String name)//  t0 t1
    {
    lock.lock();
    try
    {
    while(flag)
    // try{lock.wait();}catch(InterruptedException e){}//   t1    t0
    try{producer_con.await();}catch(InterruptedException e){}//   t1    t0

    this.name = name + count;//烤鸭1  烤鸭2  烤鸭3
    count++;//2 3 4
    System.out.println(Thread.currentThread().getName()+"...生产者5.0..."+this.name);//生产烤鸭1 生产烤鸭2 生产烤鸭3
    flag = true;
    // notifyAll();
    // con.signalAll();
    consumer_con.signal();
    }
    finally
    {
    lock.unlock();
    }

    } public  void out()// t2 t3
    {
    lock.lock();
    try
    {
    while(!flag)
    // try{this.wait();}catch(InterruptedException e){} //t2  t3
    try{cousumer_con.await();}catch(InterruptedException e){} //t2  t3
    System.out.println(Thread.currentThread().getName()+"...消费者.5.0......."+this.name);//消费烤鸭1
    flag = false;
    // notifyAll();
    // con.signalAll();
    producer_con.signal();
    }
    finally
    {
    lock.unlock();
    }

    }
    }class Producer implements Runnable
    {
    private Resource r;
    Producer(Resource r)
    {
    this.r = r;
    }
    public void run()
    {
    while(true)
    {
    r.set("烤鸭");
    }
    }
    }class Consumer implements Runnable
    {
    private Resource r;
    Consumer(Resource r)
    {
    this.r = r;
    }
    public void run()
    {
    while(true)
    {
    r.out();
    }
    }
    }class  ProducerConsumerDemo2
    {
    public static void main(String[] args) 
    {
    Resource r = new Resource();
    Producer pro = new Producer(r);
    Consumer con = new Consumer(r); Thread t0 = new Thread(pro);
    Thread t1 = new Thread(pro);
    Thread t2 = new Thread(con);
    Thread t3 = new Thread(con);
    t0.start();
    t1.start();
    t2.start();
    t3.start(); }
    }看看这个学习学习
      

  6.   

    把outInfo和setInfo中的else语句删除。就可以了。
      

  7.   

    楼主的问题是 setInfor()和OutInfor().
    楼主的代码:
            if(flag)
            /*如果flag值为false,则共享资源中没有信息,进行赋值
              如果为true,则共享资源中有信息没有打印,不进行赋值,进行wait操作
            */  
            {
                try
                {
                    this.wait();
                }
                catch (Exception e)
                {
                }
            }
            else
            {
                this.name = name;
                this.sex = sex;           
            }   
            flag=true;     //改变开关,让输入程序不能再次进行赋值,同时可以让打印程序启动
            this.notify();//唤醒输出线程
    当程序从wait()返回时是什么状态? 是输出线程将信息取走了,运行了notify(),使输入线程继续运行,这时输入线程应该进行赋值操作。而楼主的代码,却有else语句,直接跳过了赋值语句。那它就是保持原来的值,所以会出现连续的相同的值。
    把else 去掉即可。
            if(flag)
            /*如果flag值为false,则共享资源中没有信息,进行赋值
              如果为true,则共享资源中有信息没有打印,不进行赋值,进行wait操作
            */  
            {
                try
                {
                    this.wait();
                }
                catch (Exception e)
                {
                }
            }
            //else
            //{  //唤醒后执行此赋值操作。
                this.name = name;
                this.sex = sex;           
            //}   
            flag=true;     //改变开关,让输入程序不能再次进行赋值,同时可以让打印程序启动
            this.notify();//唤醒输出线程
    下面的输出线程也一样改一下。
            if (!flag)//如果flag值为ture,则共享资源中有信息,进行打印,否则等待
            {
                try
                {
                    this.wait();
                }
                catch (Exception e)
                {
                }
            }
            //else
            //{
                System.out.println(name+"......"+sex);          
            //}       
            flag=false; //改变开关,让输入程序可以进行赋值,同时让自己不能在打印
            this.notify();//唤醒输
      

  8.   


    中!!~哥们你说的太对了。/*线程共享资源类,信息类*/
    class ResourceWaitNotifyDemo
    {
    private String name;
    private String sex;
    private boolean flag=false;/*
    为什么用了显式的if...else结构,多线程就不安全了呢?Why?~Why????。 public synchronized void setInfo(String name,String sex)//信息输入函数
    {
    if(flag)
    {
    try{this.wait();}catch(Exception e){}
    }
    else
    {
    this.name = name;
    this.sex = sex;
    flag=true;  //改变开关,让输入程序不能再次进行赋值,同时可以让打印程序启动
    this.notify();//唤醒输出线程
    }

    }
    */
    /*线程安全代码*/
    public synchronized void setInfo(String name,String sex)//信息输入函数
    {
    if(flag)
    try{this.wait();}catch(Exception e){}
    this.name = name;
    this.sex = sex;
    flag=true;  //改变开关,让输入程序不能再次进行赋值,同时可以让打印程序启动
    this.notify();//唤醒输出线程
    } public synchronized void OutInfo()//信息输出函数
    {
    if(!flag)//如果flag值为ture,则共享资源中有信息,进行打印,否则等待
    {
    try
    {
    this.wait();
    }
    catch (Exception e)
    {
    }
    }
    else
    {
    System.out.println(name+"......"+sex);
    flag=false; //改变开关,让输入程序可以进行赋值,同时让自己不能在打印
    this.notify();//唤醒输入线程
    }
    }
    }
      

  9.   


    哥们我就觉得这个If...else有问题。看看我回复的那个代码,那里用的是隐式的if...else吗?
      

  10.   

    “哥们我就觉得这个If...else有问题。看看我回复的那个代码,那里用的是隐式的if...else吗?”我看不是隐式的if else. 没有else了。(else 是一旦if条件成立,就不执行了。而现在的是不管if成立与否,都要执行。
    以前看见书上说,(论坛里也很多人建议,不要用if(),而用while()更好。建议楼主试试。