请大家讨论一下线程同步的问题及实现的思路
最近接触这个问题,感觉挺陌生的。
想学习点东西,希望大家能提出自己的意见和想法,先谢谢大家了!

解决方案 »

  1.   

    java线程同步问题一般,有3种使用锁进行同步的方法 
        a.方法同步,例如public synchronized void xxx()... 
        b.静态方法同步,例如public static synchronized void xxx()... 
        c.程序块同步,例如 
            ... 
            synchronized(object oLock)    //注意:object不一定是该类的实例 
            { 
                ... 
            } 
        
        在用法a中,当某线程执行方法xxx时,jvm会锁定该类的实例,直到方法xxx执行完毕。执行xxx的过程看看成是这样的: 
        *请求得到类实例的实例锁,假如有其他线程在执行,则等待; 
        *得到实例锁,执行xxx; 
        *执行完毕,释放实例锁; 
        注意,这个过程是jvm完成的,我们只需要把某个对象方法声明为synchronized即可,实例锁可以理解为实例本身。 
        在用法b中,当某线程执行静态方法xxx时,也是有jvm控制经过以上的3个步骤,所不同的是由于此时不存在类实例(静态方法嘛),所 以用法a中实例锁被实例的类的锁取代,其实对我们编程来讲,几乎没有任何区别,我们只需要把静态方法声明为synchronized即可。 
        在用法c中,oLock可以被理解为一个传接棒,它可以是任何类的实例,当某个线程试图访问声明为synchronized的程序块的时候,jvm 判断oLock是否被锁定,假如没有被锁定,则锁定oLock并执行该程序块。执行完毕释放该锁。 
        在对象级使用锁(实例锁)通常是一种比较粗糙的方法,设想一下,假如一个对象可能去访问N个共享资源,那么假如有一个线程独占 了该对象,而仅仅是为了使用其中的一项资源的话,也会造成想访问其它资源的线程也处于堵塞状态。用程序块同步可以很好解决这个问题, 以下是使用被称为Fine_Grain_Lock的例子,看,效果是不是很high: 
    Java代码 
    class FineGrainLock {   
           MyMemberClass x, y;   
        Object xlock = new Object(), ylock = new Object();   
        public void foo() {   
              synchronized(xlock) {   
                      //access x here   
                  }   
                  //do something here - but don't use shared resources   
                   synchronized(ylock) {   
                     //access y here   
                  }   
           }   
      
          public void bar() {   
                  synchronized(this) {   
                     //access both x and y here   
                  }   
              //do something here - but don't use shared resources   
           }   
    }              class FineGrainLock {
                       MyMemberClass x, y;
                    Object xlock = new Object(), ylock = new Object();
                    public void foo() {
                          synchronized(xlock) {
                                  //access x here
                              }
                              //do something here - but don't use shared resources
                               synchronized(ylock) {
                                 //access y here
                              }
                       }                  public void bar() {
                              synchronized(this) {
                                 //access both x and y here
                              }
                          //do something here - but don't use shared resources
                       }
                }
    2.notify/wait/notifyAll,上面是交给jvm使用同步方法处理共享资源问题,可以理解为抢占型的共享资源解决方案,而使用 notify/wait/notifyall可以在程序中控制对共享资源的访问,实现一种合作型的共享资源解决方案。一个小例子: 
    Java代码 
    //WNNa:wait/notify/notifyAll   
    public class WNNa implements Runnable   
    {   
        private static Object oLock = new Object();   
        public void run()   
        {   
          try  
          {   
            synchronized(oLock)   
            {   
                TwoBoy t = (TwoBoy)Thread.currentThread();   
                if(t.getName() == "Mike")   
                {   
                    oLock.wait();   
                    t.eat();   
                    oLock.notify();   
                    oLock.wait();   
                    t.drink();   
                }   
                else  
                {   
                    t.eat();   
                    oLock.notify();   
                    oLock.wait();   
                    t.drink();   
                    oLock.notify();   
                }       
            }   
          }   
          catch(Exception ex)   
          {   
            System.out.println("Error in synchronized:" + ex.getMessage());   
          }   
        }   
        public WNNa()   
        {   
            TwoBoy t1 = new TwoBoy(this,"Tom");   
            TwoBoy t2 = new TwoBoy(this,"Mike");   
            t1.start();   
            t2.start();   
        }   
        public static void main(String argv[])   
        {   
            new WNNa();   
        }   
    }   
      
    class TwoBoy extends Thread   
    {   
        private String strName = "";   
        public TwoBoy(Runnable t,String name)   
        {   
            super(t,name);   
            strName = name;   
        }   
        public void drink()   
        {   
            System.out.println(strName + " drink!");           
        }   
        public void eat()   
        {   
            System.out.println(strName + " eat!");   
        }       
    }      //WNNa:wait/notify/notifyAll
        public class WNNa implements Runnable
        {
            private static Object oLock = new Object();
            public void run()
            {
              try
              {
                synchronized(oLock)
                {
                    TwoBoy t = (TwoBoy)Thread.currentThread();
                    if(t.getName() == "Mike")
                    {
                        oLock.wait();
                        t.eat();
                        oLock.notify();
                        oLock.wait();
                        t.drink();
                    }
                    else
                    {
                        t.eat();
                        oLock.notify();
                        oLock.wait();
                        t.drink();
                        oLock.notify();
                    }    
                }
              }
              catch(Exception ex)
              {
                System.out.println("Error in synchronized:" + ex.getMessage());
              }
            }
            public WNNa()
            {
                TwoBoy t1 = new TwoBoy(this,"Tom");
                TwoBoy t2 = new TwoBoy(this,"Mike");
                t1.start();
                t2.start();
            }
            public static void main(String argv[])
            {
                new WNNa();
            }
        }
        
        class TwoBoy extends Thread
        {
            private String strName = "";
            public TwoBoy(Runnable t,String name)
            {
                super(t,name);
                strName = name;
            }
            public void drink()
            {
                System.out.println(strName + " drink!");        
            }
            public void eat()
            {
                System.out.println(strName + " eat!");
            }    
        }
        在上面的例子中,我们可以控制线程按照业务逻辑运行,而非简单的排它的使用共享资源的问题了。 
    3.信号量方案:在有N个共享资源而有M个线程的情况下(M>>N),需要用到信号量。信号量代表可用资源的数目,线程需要使用资源时首先判 断是否有足够的资源,没有的话等待,直到其它线程释放资源为止,得到资源后,信号量应减去该线程使用的资源数目,待这些资源使用完毕 ,线程应释放这些资源。 
    Java代码 
    class Semaphore {   
           private int count;   
           public Semaphore(int n) {   
                  this.count = n;   
           }   
      
           public synchronized void acquire() {   
                  while(count == 0) {   
                     try {   
                            wait();   
                     } catch (InterruptedException e) {   
                            //keep trying   
                     }   
                  }   
                  count--;   
           }   
      
           public synchronized void release() {   
                  count++;   
                  notify(); //alert a thread that's blocking on this semaphore   
           }   
    }  
      

  2.   

    同步就是用synchronized 去写!很少写!