0

为什么通常线程示例将这么多代码放在同步块中。根据我的理解,在以下情况下,同步仅用于锁定 b 以等待和通知:

主类 ThreadA :

class ThreadA {
      public static void main(String [] args) {
         ThreadB b = new ThreadB();
         b.start();

         synchronized(b) {
            try {
               System.out.println("Waiting for b to complete...");

              b.wait();
           } catch (InterruptedException e) {}
           System.out.println("Total is: " + b.total);
           System.out.println(Thread.currentThread().getName());

        }
     }
  }

和类 ThreadB:

class ThreadB extends Thread {   
     int total;     
     public void run() {
        synchronized(this) 
        {
           System.out.println();
           for(int i=0;i<100;i++) 
           {
               System.out.println(Thread.currentThread().getName());
              total += i;
           }
           notify();
        }
     }
  }

如果我将 justwaitnotifyin 放在synchronized块中会发生什么变化:

class ThreadA {
      public static void main(String [] args) {
         ThreadB b = new ThreadB();
         b.start();
            try {
               System.out.println("Waiting for b to complete...");

                synchronized(b) {   b.wait();}
           } catch (InterruptedException e) {}
           System.out.println("Total is: " + b.total);
           System.out.println(Thread.currentThread().getName());


     }
  }
4

3 回答 3

3

根据我在以下情况下的理解,同步仅用于锁定 b 等待并通知

你的理解是错误的。

synchronized也用于:

  • 互斥,以确保一次只有一个线程执行由特定监视器“保护”的代码
  • 确保跨线程的内存访问是正确的(一个线程看到另一个线程所做的更改)

如果我将等待和通知放在同步块中会发生什么变化:

在这种特殊情况下,它将根据竞争条件产生差异 - 在原始代码中,如果新的在原始线程中到达同步块之前thread开始执行,它不会达到“等待 b 到完成”,直到第二个线程完成......此时它将永远阻塞在.wait

请注意,等待监视器是一个非常糟糕的主意,因为.Threadwait/notifyThread

简而言之,您使用的示例从各种方式开始都是一个糟糕的示例 - 但同步不仅仅用于wait/notify.

于 2013-07-31T08:56:32.473 回答
0

请注意,这不是total += iJava中的原子操作。因此,您还必须同步此构造。

您也不必同步 notify() 和 wait() 因为它们的锁是在内部处理的。

于 2013-07-31T08:56:09.660 回答
0

扩展@sk2212 的答案,增量操作不是原子的,但在高级并发原语中提供了等效的原子操作。

于 2021-09-09T15:24:58.633 回答