Java 同步列表时的操作顺序

Java 同步列表时的操作顺序,java,multithreading,synchronization,Java,Multithreading,Synchronization,我想了解Java在同步列表时是如何工作的。 假设我有以下代码: List list = Collections.synchronizedList(new ArrayList()); synchronized(list) { Iterator i = list.iterator(); while (i.hasNext()) foo(i.next()); } 一个线程(线程1)正在执行它 另一个线程(线程2)生成: 在线程1中执行上一个代码时 线程2会

我想了解Java在同步列表时是如何工作的。 假设我有以下代码:

List list = Collections.synchronizedList(new ArrayList());

synchronized(list) {
      Iterator i = list.iterator();
      while (i.hasNext())
          foo(i.next());
}
一个线程(线程1)正在执行它

另一个线程(线程2)生成:

在线程1中执行上一个代码时

线程2会等到线程1完成该代码吗?同步就像“等待另一个完成”

或者,例如,如果3个线程到达由
synchronized(list){}
包装的某个代码,它们是否只按顺序启动,而不会同时启动

  • 同步不在方法级别/代码级别。它位于对象级别
  • 如果在对象上进行同步,则访问该对象的任何线程必须首先在对象的监视器上获得锁
  • 如果thread1在监视器上具有锁,则尝试访问该对象的任何其他线程都必须等待thread1释放锁

  • 在您的示例中,线程2将等待,因为线程1已获得同步列表上的锁


    一般来说,打包在同步块中的代码在同一对象上的“下一个”同步块之前完全执行。

    Java中的同步是协作的,而不是强制的。我的意思是,您希望同步来保护您的数据,但该语言只允许您同步处理数据的代码块。您有责任确保所有可以接触数据的代码都是同步的

    (这就是其他一些答案的意思,他们说,“同步是代码级的,而不是对象级的。”

    在您的示例中,您编写了一个处理列表的同步代码块。这将阻止两个或多个线程同时进入该代码块,但通常不会阻止其他线程从其他代码块中同时处理列表,即使一个线程位于同步块中。

    另请注意:监视器对象(同步的对象)不必是您试图保护的数据的一部分。例如,您可能有两个列表;并且您可能希望保证两个列表之间的某种关系(例如,两者的长度必须相同).在这种情况下,您在哪个列表上同步?答案可能是两者都不是。例如

    private Object lock = new Object();
    private List<Foo> fooList = ...;
    private List<Bar> barList = ...;
    
    ... doSomethingFascinating(...) {
        synchronized(lock) {
            //Use your shameful imagination here.
        }
    }
    
    private Object lock=new Object();
    私人名单傻瓜=。。。;
    私有列表barList=。。。;
    …dosomethingfascing(…){
    已同步(锁定){
    //在这里发挥你可耻的想象力。
    }
    }
    
    线程2会等到线程1完成代码吗?也就是说,同步就像“等待另一个完成”

    如果某个线程获得了锁,那么在初始线程释放锁之前,其他线程都无法获得相同的锁

    或者,例如,如果3个线程到达由synchronized(list){}包装的某个代码,它们是否只按顺序启动,而不会同时启动

    是的,顺序是,但没有指定顺序。从您的角度来看,它可能是最先获得它的3个线程中的任意一个


    p.S.互斥体获取(同步)没有任何公平性。未指定哪个线程及其获取锁的时间。例如:如果有线程A持有锁,其他3个线程等待相同的锁,并且线程A在一段时间后释放锁;则这4个线程中的任何线程如果您查看
    集合背后的源代码,则(包括线程A)可以获取该锁。synchronizedList
    您将看到它创建了
    集合的实例。synchronizedList
    ,当没有传递其他值时,它使用设置为
    this
    的内部
    互斥锁进行锁定


    您的代码锁定在
    列表
    实例本身上,因此在使用
    集合时可以工作。synchronizedList(列表)
    但是使用
    List.iterator
    必须手动同步,以避免
    ConcurrentModificationException
    s.

    如果另一个线程t2更新列表,它将抛出异常一般来说,对象仍然可以访问,而不需要获得监视器谢谢Eugene。我只是不明白什么是“互斥锁”是。@Tatanan'Mutex'代表。
    private Object lock = new Object();
    private List<Foo> fooList = ...;
    private List<Bar> barList = ...;
    
    ... doSomethingFascinating(...) {
        synchronized(lock) {
            //Use your shameful imagination here.
        }
    }