繁体   English   中英

在同步方法内的线程中同步块会发生什么?

[英]What would happen with a synchronized block in a thread which is inside a synchronized method?

所以如果你有以下内容,基本上会发生什么:

class SyncTest {
    private final static List<Object> mObjectList = new ArrayList<Object>();

    public synchronized void mySyncMethod(Object object) {
        new Thread(new Runnable() {
            public void run() {
                synchronized (SyncTest.this) {
                    for (int i = 0; i < mObjectList.size(); i++) {
                        //Do something with object
                    }
                }
            }
        }).start();
    }
}
  1. 比如说,一个活动需要在不同的线程中运行,这些线程会迭代一个集合。 因此,为什么在方法中使用不同的对象创建一个线程。
  2. 这是“正确的”方式,还是有更好的方法?
  3. 这会带来任何威胁吗?

外部synchronized确保单线程访问创建新Thread的过程,而内部synchronized确保单线程访问for循环。

当然,你知道,作为编写的代码并没有太大的意义,因为内this参考是针对您的匿名内部类。 我认为你真的是指SyncTest.this所以你正在同步访问SyncTest类。 更好的方法是同步访问mObjectList

由于与内部类写this固定的,你的Thread会被阻塞,直到mySyncMethod返回。

根据您正在做的事情,最好使用其中一种Concurrent集合类型,而不是同步对List访问,因为您将获得更好的并发性。

Re-entrancy不适用于此。 这里嵌套的唯一影响是允许内部类实例访问封闭实例(包括正在使用的锁)。 同步的两件事在不同的线程中调用。 一旦创建的新线程必须由调度程序选择才能运行,所以即使它们使用相同的锁,看起来两者之间也不会有太多重叠。

调用mySyncMethod的线程获取它正在使用的SyncTest实例上的锁,然后它创建一个新的Thread,启动它,然后释放锁并继续前进。

稍后,一旦新线程启动,它必须获取SyncTest对象上的锁,该对象在它可以执行其run方法之前启动它。 如果SyncTest上的锁被其他东西使用(刚刚创建它的线程,在同一个SyncTest实例上另一个调用mySyncMethod,或者在同一个SyncTest实例上另一个调用mySyncMethod创建的另一个线程),那么它将不得不等待锁定。 然后它执行列表所需的任何操作,到达方法的末尾并释放锁。

这里有很多问题:

  • 目前还不清楚为什么你需要创建自己的线程而不是使用池,或者为什么创建方法需要同步并等待新线程在它释放锁之前启动。

  • SyncTest对象上的锁没有被封装,因此其他东西可能正在获取它,目前还不清楚是什么东西争夺锁。

  • 由于列表被定义为静态类成员,因此您有多个SyncTest对象; 你会有单独的线程搞乱相同的列表,但使用不同的锁,所以很难理解锁定点是什么。

但你所展示的并不会陷入僵局。

什么都不会发生, synchronization是关于线程的,所以即使你多次重新进入同步块,如果同步的所有者是同一个线程,它们也不会阻塞。

mySyncMethod()仅在调用它的线程可以获得该SyncTest实例中的锁的所有权时运行。

run方法可以在其不同的线程中启动,但会阻塞synchronize语句,直到THAT线程获得同一SyncTest实例的锁的所有权。

(回答假设'this'指的是外部类实例,在编辑中更正了原始帖子)

如果方法内部有同步块,则锁定仅在该块上。 并且方法内部的块可以具有不同的对象锁。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM