九鼎烹吧 关注:11贴子:645
  • 6回复贴,共1
过独木桥


IP属地:北京1楼2015-12-14 16:21回复
    IP属地:北京2楼2015-12-14 16:22
    回复
      举例说明:
      一、当两个并发线程访问同一个对象object中的这个synchronized(this)同步代码块时,一个时间内只能有一个线程得到执行。另一个线程必须等待当前线程执行完这个代码块以后才能执行该代码块。
      package ths;
      public class Thread1 implements Runnable {
      public void run() {
      synchronized(this) {
      for (int i = 0; i < 5; i++) {
      System.out.println(Thread.currentThread().getName() + " synchronized loop " + i);
      }
      }
      }
      public static void main(String[] args) {
      Thread1 t1 = new Thread1();
      Thread ta = new Thread(t1, "A");
      Thread tb = new Thread(t1, "B");
      ta.start();
      tb.start();
      }
      }
      结果:
      A synchronized loop 0
      A synchronized loop 1
      A synchronized loop 2
      A synchronized loop 3
      A synchronized loop 4
      B synchronized loop 0
      B synchronized loop 1
      B synchronized loop 2
      B synchronized loop 3
      B synchronized loop 4


      IP属地:北京4楼2015-12-14 16:23
      回复
        二、然而,当一个线程访问object的一个synchronized(this)同步代码块时,另一个线程仍然可以访问该object中的非synchronized(this)同步代码块。
        package ths;
        public class Thread2 {
        public void m4t1() {
        synchronized(this) {
        int i = 5;
        while( i-- > 0) {
        System.out.println(Thread.currentThread().getName() + " : " + i);
        try {
        Thread.sleep(500);
        } catch (InterruptedException ie) {
        }
        }
        }
        }
        public void m4t2() {
        int i = 5;
        while( i-- > 0) {
        System.out.println(Thread.currentThread().getName() + " : " + i);
        try {
        Thread.sleep(500);
        } catch (InterruptedException ie) {
        }
        }
        }
        public static void main(String[] args) {
        final Thread2 myt2 = new Thread2();
        Thread t1 = new Thread( new Runnable() { public void run() { myt2.m4t1(); } }, "t1" );
        Thread t2 = new Thread( new Runnable() { public void run() { myt2.m4t2(); } }, "t2" );
        t1.start();
        t2.start();
        }
        }
        结果:
        t1 : 4
        t2 : 4
        t1 : 3
        t2 : 3
        t1 : 2
        t2 : 2
        t1 : 1
        t2 : 1
        t1 : 0
        t2 : 0


        IP属地:北京5楼2015-12-14 16:23
        回复
          三、尤其关键的是,当一个线程访问object的一个synchronized(this)同步代码块时,其他线程对object中所有其它synchronized(this)同步代码块的访问将被阻塞。
          //修改Thread2.m4t2()方法:
          public void m4t2() {
          synchronized(this) {
          int i = 5;
          while( i-- > 0) {
          System.out.println(Thread.currentThread().getName() + " : " + i);
          try {
          Thread.sleep(500);
          } catch (InterruptedException ie) {
          }
          }
          }
          }
          结果:
          t1 : 4
          t1 : 3
          t1 : 2
          t1 : 1
          t1 : 0
          t2 : 4
          t2 : 3
          t2 : 2
          t2 : 1
          t2 : 0


          IP属地:北京6楼2015-12-14 16:23
          回复
            五、以上规则对其它对象锁同样适用:
            package ths;
            public class Thread3 {
            class Inner {
            private void m4t1() {
            int i = 5;
            while(i-- > 0) {
            System.out.println(Thread.currentThread().getName() + " : Inner.m4t1()=" + i);
            try {
            Thread.sleep(500);
            } catch(InterruptedException ie) {
            }
            }
            }
            private void m4t2() {
            int i = 5;
            while(i-- > 0) {
            System.out.println(Thread.currentThread().getName() + " : Inner.m4t2()=" + i);
            try {
            Thread.sleep(500);
            } catch(InterruptedException ie) {
            }
            }
            }
            }
            private void m4t1(Inner inner) {
            synchronized(inner) { //使用对象锁
            inner.m4t1();
            }
            private void m4t2(Inner inner) {
            inner.m4t2();
            }
            public static void main(String[] args) {
            final Thread3 myt3 = new Thread3();
            final Inner inner = myt3.new Inner();
            Thread t1 = new Thread( new Runnable() {public void run() { myt3.m4t1(inner);} }, "t1");
            Thread t2 = new Thread( new Runnable() {public void run() { myt3.m4t2(inner);} }, "t2");
            t1.start();
            t2.start();
            }
            }
            结果:
            尽管线程t1获得了对Inner的对象锁,但由于线程t2访问的是同一个Inner中的非同步部分。所以两个线程互不干扰。
            t1 : Inner.m4t1()=4
            t2 : Inner.m4t2()=4
            t1 : Inner.m4t1()=3
            t2 : Inner.m4t2()=3
            t1 : Inner.m4t1()=2
            t2 : Inner.m4t2()=2
            t1 : Inner.m4t1()=1
            t2 : Inner.m4t2()=1
            t1 : Inner.m4t1()=0
            t2 : Inner.m4t2()=0
            现在在Inner.m4t2()前面加上synchronized:
            private synchronized void m4t2() {
            int i = 5;
            while(i-- > 0) {
            System.out.println(Thread.currentThread().getName() + " : Inner.m4t2()=" + i);
            try {
            Thread.sleep(500);
            } catch(InterruptedException ie) {
            }
            }
            }
            结果:
            尽管线程t1与t2访问了同一个Inner对象中两个毫不相关的部分,但因为t1先获得了对Inner的对象锁,所以t2对Inner.m4t2()的访问也被阻塞,因为m4t2()是Inner中的一个同步方法。
            t1 : Inner.m4t1()=4
            t1 : Inner.m4t1()=3
            t1 : Inner.m4t1()=2
            t1 : Inner.m4t1()=1
            t1 : Inner.m4t1()=0
            t2 : Inner.m4t2()=4
            t2 : Inner.m4t2()=3
            t2 : Inner.m4t2()=2
            t2 : Inner.m4t2()=1
            t2 : Inner.m4t2()=0


            IP属地:北京8楼2015-12-14 16:23
            回复
              同步方法和同步代码块的区别是什么?
              在Java语言中,每一个对象有一把锁。线程可以使用synchronized关键字来获取对象上的锁。synchronized关键字可应用在方法级别(粗粒度锁)或者是代码块级别(细粒度锁)。


              IP属地:北京9楼2015-12-31 10:48
              回复