4

所以基本上如果你有以下情况会发生什么:

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. 这会带来任何威胁吗?
4

5 回答 5

3

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

当然,您意识到编写的代码没有多大意义,因为内部this引用是针对您的匿名内部类的。我认为您的意思SyncTest.this是您正在同步对SyncTest课程的访问。更好的是同步访问mObjectList.

正如固定内部类所写的那样this,您Thread将阻塞直到mySyncMethod返回。

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

于 2014-05-15T16:34:47.373 回答
3

重入不适用于此处。这里嵌套的唯一影响是允许内部类实例访问封闭实例(包括正在使用的锁)。同步的两件事在不同的线程中被调用。新线程一旦创建,必须先由调度程序选择,然后才能运行,因此即使它们使用相同的锁,两者之间似乎不太可能有太多重叠。

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

稍后,一旦新线程启动,它必须先获取启动它的 SyncTest 对象上的锁,然后才能执行其运行方法。如果 SyncTest 上的锁正在被其他东西使用(或者是刚刚创建它的线程,在同一个 SyncTest 实例上对 mySyncMethod 的另一个调用,或者在同一个 SyncTest 实例上对 mySyncMethod 的另一个调用创建的另一个线程),那么它必须等待获得锁。然后它对列表做任何需要做的事情,到达方法的末尾并释放锁。

这里有很多问题:

  • 不清楚为什么需要创建自己的线程而不是使用池,或者为什么创建方法需要同步并等待新线程启动才能释放其锁定。

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

  • 由于列表被定义为静态类成员,因此您有多个 SyncTest 对象;您将有单独的线程处理同一个列表,但使用不同的锁,因此很难理解锁定的意义。

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

于 2014-05-15T16:51:30.307 回答
0

就线程而言,什么都不会发生,synchronization因此即使您多次重新进入同步块,如果同步的所有者是同一个线程,它们也不会阻塞。

于 2014-05-15T16:28:20.747 回答
0

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

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

(答案假设“this”指的是外部类实例,在对原始帖子的编辑中已更正)

于 2014-05-15T16:32:17.230 回答
0

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

于 2014-05-15T16:35:48.303 回答