有没有办法使用同步的方法,而不是一个synchronized块的优势呢?

问题描述 投票:393回答:23

任何一个可以告诉我synchronized方法的优势用一个例子synchronized块?

java multithreading concurrency locking synchronized
23个回答
425
投票

谁能告诉我,同步方法的优势结合实例的synchronized块?谢谢。

没有使用同步方法超过块的一个明显的优势。

也许只有一个(但我不会把它的优势)是你不需要包含对象引用this

方法:

public synchronized void method() { // blocks "this" from here.... 
    ...
    ...
    ...
} // to here

块:

public void method() { 
    synchronized( this ) { // blocks "this" from here .... 
        ....
        ....
        ....
    }  // to here...
}

看到?没有任何优势可言。

块也有一些对方法的优点,虽然,大多是在灵活性,因为你可以使用另一个对象的锁,而同步的方法将锁定整个对象。

相比:

// locks the whole object
... 
private synchronized void someInputRelatedWork() {
    ... 
}
private synchronized void someOutputRelatedWork() {
    ... 
}

// Using specific locks
Object inputLock = new Object();
Object outputLock = new Object();

private void someInputRelatedWork() {
    synchronized(inputLock) { 
        ... 
    } 
}
private void someOutputRelatedWork() {
    synchronized(outputLock) { 
        ... 
    }
}

此外,如果该方法的增长仍然可以保持彼此分离,同步部分:

 private void method() {
     ... code here
     ... code here
     ... code here
    synchronized( lock ) { 
        ... very few lines of code here
    }
     ... code here
     ... code here
     ... code here
     ... code here
}

6
投票

同步方法可以使用反射API被检查。这对于测试的一些合同,如在模型中的所有方法都是同步有用。

下面的代码片段打印哈希表的所有同步方法:

for (Method m : Hashtable.class.getMethods()) {
        if (Modifier.isSynchronized(m.getModifiers())) {
            System.out.println(m);
        }
}

5
投票

使用synchronized块重要提示:小心你的锁对象使用什么!

以上从user2277816的代码片段示出了在为一个字符串文字的参考这点用作锁定对象。要知道,字符串字面量在Java中自动实习,你应该开始看到这个问题:每一段代码,关于文字“锁”同步,共享相同的锁!这很容易导致与代码完全无关件死锁。

这并不是说你必须要小心只有String对象。盒装原语也有危险,因为自动装箱和方法的valueOf可以重复使用相同的对象,根据不同的价值。

欲了解更多信息,请参阅:https://www.securecoding.cert.org/confluence/display/java/LCK01-J.+Do+not+synchronize+on+objects+that+may+be+reused


5
投票

经常使用的一个方法级别的锁是太失礼。为什么锁定一块不通过锁定一整方法访问任何共享资源的代码。由于每个对象都有一个锁,你可以创建实现块级同步虚拟对象。因为它不锁定整个方法的块级是更有效的。

这里是一些例子

方法级

class MethodLevel {

  //shared among threads
SharedResource x, y ;

public void synchronized method1() {
   //multiple threads can't access
}
public void synchronized method2() {
  //multiple threads can't access
}

 public void method3() {
  //not synchronized
  //multiple threads can access
 }
}

块级

class BlockLevel {
  //shared among threads
  SharedResource x, y ;

  //dummy objects for locking
  Object xLock = new Object();
  Object yLock = new Object();

    public void method1() {
     synchronized(xLock){
    //access x here. thread safe
    }

    //do something here but don't use SharedResource x, y
    // because will not be thread-safe
     synchronized(xLock) {
       synchronized(yLock) {
      //access x,y here. thread safe
      }
     }

     //do something here but don't use SharedResource x, y
     //because will not be thread-safe
    }//end of method1
 }

[编辑]

对于像CollectionVector Hashtable它们同步时ArrayListHashMap不是你不必设置synchronized关键字或调用集合同步方法:

Map myMap = Collections.synchronizedMap (myMap); // single lock for the entire map
List myList = Collections.synchronizedList (myList); // single lock for the entire list

5
投票

唯一的区别:同步块允许不像同步方法粒状锁定

基本上synchronized块或方法已被用于通过避免内存不一致性错误写入线程安全代码。

这个问题是很旧,在过去的7年中,许多事情都发生了变化。全新的编程结构已经引入了线程安全。

您可以通过使用高级并发API,而不是synchronied块实现线程安全。本文档page提供了良好的编程构造来实现线程安全。

Lock Objects支持锁定,简化了许多并发应用程序的成语。

Executors定义一个高层次的API,用于启动和管理线程。通过java.util.concurrent中提供的Executor实现提供了线程池管理器适合大规模应用。

Concurrent Collections更容易地管理数据的大集合,而且可以大大减少同步的需要。

Atomic Variables具备的功能,最大限度地减少同步,并有助于避免内存一致性错误。

ThreadLocalRandom(JDK 7中)提供了从多个线程有效地产生伪随机数。

更好的替代品同步是ReentrantLock,它采用Lock API

使用synchronized方法和语句访问具有相同的基本行为和语义的隐式监视器锁定一个折返互斥锁,但功能更强大。

例如与锁:

class X {
   private final ReentrantLock lock = new ReentrantLock();
   // ...

   public void m() {
     lock.lock();  // block until condition holds
     try {
       // ... method body
     } finally {
       lock.unlock()
     }
   }
 }

请参考其他编程结构过于java.util.concurrentjava.util.concurrent.atomic包。

请参阅此相关的问题太多:

Synchronization vs Lock


4
投票

用于锁定同步方法中的所有对象的同步块被用于锁定特定对象


3
投票

一般来说,这些大多不是被明确 - 这就是正在使用VS隐含此对象的对象监视器同其他。 synchronized方法,我觉得有时忽略的一个缺点是,在使用“this”引用对您同步离开开放的外部对象锁定对同一对象的可能性。这可以是一个非常微妙的错误,如果你碰到它。同步在内部明确的对象或其他现有字段可避免此问题,完全封装的同步。


2
投票

如已经所述同步这里块可以使用用户定义的变量作为锁定对象,当同步功能只有“这个”使用。当然,你可以用它应该是同步的功能区操作。但是大家都说同步功能和块覆盖整个功能没有什么区别使用“this”的锁定对象。这是不正确的,不同的是,这将在两种情况下会产生字节码。在同步块使用的情况下,应分配保持提及“这个”局部变量。而作为结果,我们需要有一点点大的大小的功能(不相关的,如果你只有功能极少数)。

你可以在这里找到差异的更详细的解释:http://www.artima.com/insidejvm/ed2/threadsynchP.html


2
投票

在同步方法的情况下,锁将上的对象来获取。但是,如果你用synchronized块去,你必须指定在其上的锁将被收购对象的选择。

例如:

    Class Example {
    String test = "abc";
    // lock will be acquired on String  test object.
    synchronized (test) {
        // do something
    }

   lock will be acquired on Example Object
   public synchronized void testMethod() {
     // do some thing
   } 

   }

2
投票

我知道这是一个老问题,但我在这里的答复快速阅读,我真的没有看到任何人提到,在次synchronized方法可能是错误的锁。 从Java并发实践(第72页。):

public class ListHelper<E> {
  public List<E> list = Collections.syncrhonizedList(new ArrayList<>());
...

public syncrhonized boolean putIfAbsent(E x) {
 boolean absent = !list.contains(x);
if(absent) {
 list.add(x);
}
return absent;
}

上面的代码有被线程安全的外观。然而,在现实中却并非如此。在这种情况下是在该类的实例中得到的锁。但是,它有可能被另一个线程不使用这种方法来修改列表。正确的做法是使用

public boolean putIfAbsent(E x) {
 synchronized(list) {
  boolean absent = !list.contains(x);
  if(absent) {
    list.add(x);
  }
  return absent;
}
}

上面的代码会阻止试图从修改列表,直到同步块已完成修改列表中的所有线程。


2
投票

作为一个实际问题,超过同步块同步方法的优点是,它们是更白痴抗性;因为你不能选择任意对象锁定,你不能滥用同步方法语法做愚蠢的事情,例如把基于文字或锁定上,但未通过螺纹之下变出了一个可变字段的内容。

在另一方面,与同步方法,你不能保护锁被任何线程可以获取到对象的引用,得到收购。

因此,使用同步作为方法修改是在保护你的牛orkers从伤害自己更好,而在与私人最终锁定对象一起使用synchronized块是在保护自己的代码从奶牛orkers更好。


138
投票

唯一的区别在于,同步块可以选择它同步于哪个对象。一个同步方法只可以使用'this'(或相应的类实例为同步类方法)。例如,这些在语义上是等效的:

synchronized void foo() {
  ...
}

void foo() {
    synchronized (this) {
      ...
    }
}

后者是更灵活的,因为它可以为任何对象的相关联的锁,通常是一个成员变量竞争。它也更精细,因为你可以有方法中执行前和后挡,但仍并发代码。当然,你可以很容易地通过重构并发代码放到单独的非同步方法使用synchronized方法。无论使用何种使得代码更容易理解。


1
投票

从Java规范总结:http://www.cs.cornell.edu/andru/javaspec/17.doc.html

同步声明(§14.17)计算对一个对象的引用;然后尝试执行对象上的锁的动作,直到锁定动作已经成功完成不进一步进行。 ...

一个同步方法(§8.4.3.5)自动执行,当它被调用的锁定动作;不执行它的身体,直到锁定动作已成功完成。如果该方法是一个实例方法,它锁定与它被调用的量,实例相关联的锁(即,将在方法的主体的执行期间被称为此的对象)。如果该方法是静态的,它锁定与表示在其被定义方法的类的类对象相关联的锁。 ...

基于这些描述,我会说,大多数以前的答案是正确的,同步的方法可能是静态方法,你本来要弄清楚如何让代表类中的方法是“Class对象特别有用定义“。

编辑:我本来以为这些都是实际的Java规范的报价。明确的是该网页是规范的总结/解释


1
投票

TLDR;既不使用synchronized改性剂,也不是synchronized(this){...}表达但synchronized(myLock){...}其中myLock是最终实例字段保持私有对象。


使用关于方法声明的synchronized改性剂和在该方法中体内表达synchronized(..){ }此之间的差:

  • 在方法的签名中指定的synchronized修改 是在所生成的JavaDoc可见, 对于reflection测试方法的修改器时是通过编程Modifier.SYNCHRONIZED确定, 需要更少的输入和缩进相比synchronized(this) { .... },和 (取决于你的IDE)是在类大纲和代码完成可见, 使用this对象作为锁定在非静态方法或在静态方法中声明时封闭类声明时。
  • synchronized(...){...}表达式允许您 只同步方法的身体部分的执行, 被构造函数或(static)初始化块内使用, 选择其控制同步访问锁定对象。

然而,使用synchronized改性剂或与synchronized(...) {...} this作为锁定对象(如在synchronized(this) {...}),具有相同的缺点。两者都使用它自己的实例作为锁定对象同步的。这是危险的,因为不仅该对象本身,而是任何其他外部物体/代码保存到该对象的引用也可以使用它作为与潜在的严重的副作用(性能退化和deadlocks)一个同步锁。

因此最好的做法是用如synchronized锁定对象,但锁定对象私有此对象既不使用synchronized(...)改性剂,也没有this表达结合。例如:

public class MyService {
    private final lock = new Object();

    public void doThis() {
       synchronized(lock) {
          // do code that requires synchronous execution
        }
    }

    public void doThat() {
       synchronized(lock) {
          // do code that requires synchronous execution
        }
    }
}

您还可以使用多种锁对象,但特殊照顾需要采取以确保本使用嵌套时不会导致死锁。

public class MyService {
    private final lock1 = new Object();
    private final lock2 = new Object();

    public void doThis() {
       synchronized(lock1) {
          synchronized(lock2) {
              // code here is guaranteed not to be executes at the same time
              // as the synchronized code in doThat() and doMore().
          }
    }

    public void doThat() {
       synchronized(lock1) {
              // code here is guaranteed not to be executes at the same time
              // as the synchronized code in doThis().
              // doMore() may execute concurrently
        }
    }

    public void doMore() {
       synchronized(lock2) {
              // code here is guaranteed not to be executes at the same time
              // as the synchronized code in doThis().
              // doThat() may execute concurrently
        }
    }
}

1
投票

我想这个问题是关于有双重检查锁定线程安全辛格尔顿和延迟初始化之间的差异。我总是引用这篇文章的时候,我需要实现一些特定的单。

那么,这是一个线程安全的Singleton:

// Java program to create Thread Safe 
// Singleton class 
public class GFG  
{ 
  // private instance, so that it can be 
  // accessed by only by getInstance() method 
  private static GFG instance; 

  private GFG()  
  { 
    // private constructor 
  } 

 //synchronized method to control simultaneous access 
  synchronized public static GFG getInstance()  
  { 
    if (instance == null)  
    { 
      // if instance is null, initialize 
      instance = new GFG(); 
    } 
    return instance; 
  } 
} 

优点:

  1. 懒初始化是可能的。
  2. 它是线程安全的。

缺点:

  1. getInstance()方法是同步的,从而它会导致性能降低作为多个线程不能同时访问它。

这是一个延迟初始化有双重检查锁定:

// Java code to explain double check locking 
public class GFG  
{ 
  // private instance, so that it can be 
  // accessed by only by getInstance() method 
  private static GFG instance; 

  private GFG()  
  { 
    // private constructor 
  } 

  public static GFG getInstance() 
  { 
    if (instance == null)  
    { 
      //synchronized block to remove overhead 
      synchronized (GFG.class) 
      { 
        if(instance==null) 
        { 
          // if instance is null, initialize 
          instance = new GFG(); 
        } 

      } 
    } 
    return instance; 
  } 
} 

优点:

  1. 懒初始化是可能的。
  2. 这也是线程安全的。
  3. 性能,因为synchronized关键字的减少被克服。

缺点:

  1. 第一次,它可能会影响性能。
  2. 至于利弊。双重检查锁定方法的是可以忍受的,因此它可以被用于高性能的多线程应用程序。

请参考本文的详细信息:

https://www.geeksforgeeks.org/java-singleton-design-pattern-practices-examples/


-3
投票

与线程同步。 1)在一个线程它不工作不会使用同步(这一点)。与(本)同步使用当前线程作为锁定螺纹对象。由于每个线程都是独立于其他线程的,还有同步的NO协调。 2)的代码显示,在Java 1.6的Mac上的方法同步不起作用测试。 3)同步的(lockObj)其中lockObj是同步上,将工作的所有线程的公共共享对象。 4)ReenterantLock.lock()和.unlock()的工作。请参阅该Java教程。

下面的代码显示了这些点。它还包含将被替换为ArrayList中的线程安全的载体,表明许多线程加入到Vector不会丢失任何信息,而用一个ArrayList同样可以丢失信息。 0)当前代码显示的信息损失,由于竞态条件A)注释当前标记的一条线,并取消它上面的一条线,然后运行,方法失去数据,但它不应该。 B)反向步骤A中,取消B和//结束块}。然后运行看到的结果没有数据C的丢失)注释掉B,取消注释C.运行,见上同步(这)失去数据,如所预期。没有足够的时间来完成所有的变化,希望这有助于。如果同步上(本),或方法同步作品,请注明您测试的是什么版本的Java和操作系统。谢谢。

import java.util.*;

/** RaceCondition - Shows that when multiple threads compete for resources 
     thread one may grab the resource expecting to update a particular 
     area but is removed from the CPU before finishing.  Thread one still 
     points to that resource.  Then thread two grabs that resource and 
     completes the update.  Then thread one gets to complete the update, 
     which over writes thread two's work.
     DEMO:  1) Run as is - see missing counts from race condition, Run severa times, values change  
            2) Uncomment "synchronized(countLock){ }" - see counts work
            Synchronized creates a lock on that block of code, no other threads can 
            execute code within a block that another thread has a lock.
        3) Comment ArrayList, unComment Vector - See no loss in collection
            Vectors work like ArrayList, but Vectors are "Thread Safe"
         May use this code as long as attribution to the author remains intact.
     /mf
*/ 

public class RaceCondition {
    private ArrayList<Integer> raceList = new ArrayList<Integer>(); // simple add(#)
//  private Vector<Integer> raceList = new Vector<Integer>(); // simple add(#)

    private String countLock="lock";    // Object use for locking the raceCount
    private int raceCount = 0;        // simple add 1 to this counter
    private int MAX = 10000;        // Do this 10,000 times
    private int NUM_THREADS = 100;    // Create 100 threads

    public static void main(String [] args) {
    new RaceCondition();
    }

    public RaceCondition() {
    ArrayList<Thread> arT = new ArrayList<Thread>();

    // Create thread objects, add them to an array list
    for( int i=0; i<NUM_THREADS; i++){
        Thread rt = new RaceThread( ); // i );
        arT.add( rt );
    }

    // Start all object at once.
    for( Thread rt : arT ){
        rt.start();
    }

    // Wait for all threads to finish before we can print totals created by threads
    for( int i=0; i<NUM_THREADS; i++){
        try { arT.get(i).join(); }
        catch( InterruptedException ie ) { System.out.println("Interrupted thread "+i); }
    }

    // All threads finished, print the summary information.
    // (Try to print this informaiton without the join loop above)
    System.out.printf("\nRace condition, should have %,d. Really have %,d in array, and count of %,d.\n",
                MAX*NUM_THREADS, raceList.size(), raceCount );
    System.out.printf("Array lost %,d. Count lost %,d\n",
             MAX*NUM_THREADS-raceList.size(), MAX*NUM_THREADS-raceCount );
    }   // end RaceCondition constructor



    class RaceThread extends Thread {
    public void run() {
        for ( int i=0; i<MAX; i++){
        try {
            update( i );        
        }    // These  catches show when one thread steps on another's values
        catch( ArrayIndexOutOfBoundsException ai ){ System.out.print("A"); }
        catch( OutOfMemoryError oome ) { System.out.print("O"); }
        }
    }

    // so we don't lose counts, need to synchronize on some object, not primitive
    // Created "countLock" to show how this can work.
    // Comment out the synchronized and ending {, see that we lose counts.

//    public synchronized void update(int i){   // use A
    public void update(int i){                  // remove this when adding A
//      synchronized(countLock){            // or B
//      synchronized(this){             // or C
        raceCount = raceCount + 1;
        raceList.add( i );      // use Vector  
//          }           // end block for B or C
    }   // end update

    }   // end RaceThread inner class


} // end RaceCondition outter class

76
投票

synchronized方法

优点:

  • 您的IDE可以指示同步方法。
  • 语法是更紧凑。
  • 力施加到同步块被划分到单独的方法。

缺点:

  • 同步到这一点,所以能够外人也与其同步。
  • 这是很难同步块外移动代码。

synchronized块

优点:

  • 允许使用一个私有变量的锁,因此迫使锁留在类中。
  • synchronized块可以通过搜索到的变量参考文献中找到。

缺点:

  • 语法是比较复杂,所以使代码难以阅读。

我个人更喜欢使用只专注于事情需要同步类同步方法。这种类应该尽可能的小,所以它应该很容易审查的同步。其他人不应该需要关心的同步。


36
投票

主要的区别是,如果使用一个同步块则可能比这以外的对象,其允许更加灵活上锁定。

假设你有一个消息队列和多个消息生产者和消费者。我们不想生产商相互干扰,但消费者应该可以,而不必等待生产者检索消息。所以,我们只是创建一个对象

Object writeLock = new Object();

而从现在开始每次生产者要添加新的消息,我们刚刚锁定上:

synchronized(writeLock){
  // do something
}

所以,消费者仍然可以阅读,生产者将被锁定。


30
投票

同步方法

同步方法有两个作用。 首先,当一个线程正在执行的对象同步方法,来调用同步对于相同的对象块(挂起执行),直到第一线程的方法的全部其他线程与该对象进行。

其次,当一个同步方法退出时,它自动地建立与用于相同对象的同步方法的任何后续调用一个之前发生的关系。这保证了更改对象的状态是所有线程可见。

请注意,构造函数不能同步 - 使用synchronized关键字与构造函数是一个语法错误。同步构造没有意义的,因为正在建设中,而它仅仅是创建一个对象的线程应该能够访问它。

synchronized声明

不同于同步方法,同步语句必须指定提供的内部锁对象:大多数情况下我使用它来同步访问列表或地图,但我不想阻止访问对象的所有方法。

问:内在锁和同步同步是围绕被称为内在锁或监视器锁定内部实体建造。 (API规范通常是指这个实体简称为“显示器”。)内在锁在同步的两个方面发挥作用:执行一个对象的状态和建立之前发生是能见度的关系至关重要独占访问。

每个对象都有一个与之关联的内部锁。按照惯例,需要一个对象的字段独家一致的访问一个线程访问之前,获取物体的内部锁,然后当它与他们所做的释放内部锁。一个线程被说成自己的,它已经收购了锁和释放锁的时间之间的内在锁。只要一个线程拥有一个内部锁,没有其他线程可以获取同样的锁。当它试图获取锁,其他的线程将阻塞。

package test;

public class SynchTest implements Runnable {  
    private int c = 0;

    public static void main(String[] args) {
        new SynchTest().test();
    }

    public void test() {
        // Create the object with the run() method
        Runnable runnable = new SynchTest();
        Runnable runnable2 = new SynchTest();
        // Create the thread supplying it with the runnable object
        Thread thread = new Thread(runnable,"thread-1");
        Thread thread2 = new Thread(runnable,"thread-2");
//      Here the key point is passing same object, if you pass runnable2 for thread2,
//      then its not applicable for synchronization test and that wont give expected
//      output Synchronization method means "it is not possible for two invocations
//      of synchronized methods on the same object to interleave"

        // Start the thread
        thread.start();
        thread2.start();
    }

    public synchronized  void increment() {
        System.out.println("Begin thread " + Thread.currentThread().getName());
        System.out.println(this.hashCode() + "Value of C = " + c);
//      If we uncomment this for synchronized block, then the result would be different
//      synchronized(this) {
            for (int i = 0; i < 9999999; i++) {
                c += i;
            }
//      }
        System.out.println("End thread " + Thread.currentThread().getName());
    }

//    public synchronized void decrement() {
//        System.out.println("Decrement " + Thread.currentThread().getName());
//    }

    public int value() {
        return c;
    }

    @Override
    public void run() {
        this.increment();
    }
}

交叉检查不同的输出与同步方法,块和不同步。


29
投票

注:静态同步方法和块的Class对象上工作。

public class MyClass {
   // locks MyClass.class
   public static synchronized void foo() {
// do something
   }

   // similar
   public static void foo() {
      synchronized(MyClass.class) {
// do something
      }
   }
}

17
投票

当Java编译器转换你的源代码的字节代码,它处理同步方法和同步块非常不同。

当JVM执行一个同步方法,正在执行的线程标识,所述方法的method_info结构具有ACC_SYNCHRONIZED标志设置,则它自动获取对象的锁,调用该方法,并释放该锁。如果发生异常,该线程将自动解除锁定。

同步的方法块,而另一方面,绕过JVM的内置支持采集对象的锁,异常处理,并要求该功能可以明确地写在字节码。如果用synchronized块读取的方法的字节代码,你会看到十几额外的操作来管理此功能。

这表明呼叫同时生成一个同步的方法和同步块:

public class SynchronizationExample {
    private int i;

    public synchronized int synchronizedMethodGet() {
        return i;
    }

    public int synchronizedBlockGet() {
        synchronized( this ) {
            return i;
        }
    }
}

该方法synchronizedMethodGet()生成随后的字节代码:

0:  aload_0
1:  getfield
2:  nop
3:  iconst_m1
4:  ireturn

下面是从synchronizedBlockGet()方法的字节码:

0:  aload_0
1:  dup
2:  astore_1
3:  monitorenter
4:  aload_0
5:  getfield
6:  nop
7:  iconst_m1
8:  aload_1
9:  monitorexit
10: ireturn
11: astore_2
12: aload_1
13: monitorexit
14: aload_2
15: athrow

同步方法和块之间的一个显著区别在于,同步块通常降低锁的范围。由于锁定的范围是成反比的性能,它始终是更好地锁定的唯一代码关键部分。一个使用同步块的最好的例子是double checked locking in Singleton pattern其中,代替锁定整个getInstance()方法我们只锁定的,其被用来创建Singleton实例代码临界区。这大大提高性能,因为锁定只需要一分或两次。

虽然使用synchronized方法,你需要,如果你混合静态同步和非同步的静态方法来格外小心。


12
投票

大多数情况下我使用它来同步访问列表或地图,但我不想阻止访问对象的所有方法。

在下面的代码一个线程修改列表将不阻塞等待被修改地图的螺纹。如果其方法是在对象上同步,然后每个方法将不得不等待,即使修改,他们正在就不会发生冲突。

private List<Foo> myList = new ArrayList<Foo>();
private Map<String,Bar) myMap = new HashMap<String,Bar>();

public void put( String s, Bar b ) {
  synchronized( myMap ) {
    myMap.put( s,b );
    // then some thing that may take a while like a database access or RPC or notifying listeners
  }
}

public void hasKey( String s, ) {
  synchronized( myMap ) {
    myMap.hasKey( s );
  }
}

public void add( Foo f ) {
  synchronized( myList ) {
    myList.add( f );
// then some thing that may take a while like a database access or RPC or notifying listeners
  }
}

public Thing getMedianFoo() {
  Foo med = null;
  synchronized( myList ) {
    Collections.sort(myList);
    med = myList.get(myList.size()/2); 
  }
  return med;
}

7
投票

随着synchronized块,你可以有多个同步器,使多个同时但不冲突的东西都可以在同一时间去。

© www.soinside.com 2019 - 2024. All rights reserved.