문제

So basically what would happen if you have the following:

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. Say, an activity needs to run in different threads which iterates over a collection. Hence why creating a thread in the method with different objects.
  2. Is this the "right" way, or perhaps there is a better way?
  3. Does this present any threats?
도움이 되었습니까?

해결책

Re-entrancy doesn't apply here. The only impact of nesting here is allowing the inner class instances to have access to the enclosing instance (including the lock being used). The two things that are synchronized are called in different threads. The new thread once created will have to get chosen by the scheduler before it can run so even though these are using the same lock it would seem unlikely there would be much overlap between the two.

The thread that calls mySyncMethod acquires the lock on the instance of SyncTest it's using, then it creates a new Thread, starts it, then releases the lock and goes on its way.

Later once the new thread starts it has to acquire the lock on the SyncTest object that started it before it can execute its run method. If the lock on SyncTest is in use by something else (either the thread that just created it, another call to mySyncMethod on the same SyncTest instance, or another thread created by another call to mySyncMethod on the same SyncTest instance) then it would have to wait around to get the lock. Then it does whatever it needs to with the list, gets to the end of the method and releases the lock.

There are a lot of problems here:

  • It's unclear why you need to create your own thread rather than use a pool, or why the creating method needs to synchronize and wait around for the new thread to start before it can release its lock.

  • The lock on the SyncTest object is not encapsulated so other things could be acquiring it, it's unclear what things are contending for the lock.

  • Since the list is defined as a static class member, you have more than one SyncTest object; you're going to have separate threads messing with the same list, but using different locks, so it's hard to understand what the point of locking is.

But what you've shown isn't going to deadlock.

다른 팁

The outer synchronized ensures single thread access to the process of creating the new Thread while the inner synchronized ensures single thread access to the for loop.

Of course you realize that as written the code doesn't make much sense because the inner this reference is targeted at your anonymous inner class. I think you really mean SyncTest.this so you are synchronizing access to the SyncTest class. Even better would be to synchronize access to mObjectList.

As written with the inner class this fixed, your Thread would block until mySyncMethod returned.

Depending on what you are doing you might be better off using one of the Concurrent collection types rather than synchronizing access to your List as you'll get better concurrency.

Nothing would happen, synchronization is with respect to the thread, so even if you re-enter the sync block many times they would not block if the owner of the sync is the same Thread.

mySyncMethod() will only run when the thread calling it can gain ownership of the lock in that instance of SyncTest.

The run method could start in its different thread, but will block on the synchronize statement until THAT thread gains ownership of the lock for the same instance of SyncTest.

(answer assumed that 'this' referred to the outer class instance, which was corrected in the edit to the original post)

If you have synchronization block inside the method then the lock is on that block only. And block inside the method can have different object's lock.

라이센스 : CC-BY-SA ~와 함께 속성
제휴하지 않습니다 StackOverflow
scroll top