当监视器对象在多个线程之间共享时,Synchronized 关键字无法按预期工作

问题描述 投票:0回答:2

我正在练习java多线程和并发。所以我目前正在研究 wait() 和 notification() 功能。我创建了以下代码


public class WaitAndNotifyTest {

    public static void main(String[] args) {
        Object testString = new Object();
        RunnableImplTest runnableImplTest = new RunnableImplTest(testString);
        for(int i=0; i<5; i++) {
            Thread thread = new Thread(runnableImplTest);
            System.out.println("Created thread " + thread.getName());
            thread.start();
        }
        
        synchronized (testString) {
            testString.notify();
        }

    }
    
    private static class RunnableImplTest implements Runnable{
        
        private Object str;
        
        public RunnableImplTest(Object str) {
            this.str = str;
        }

        @Override
        public void run() {
            try {
                synchronized (str) {
                    System.out.println("Sending in waiting state for thread "+Thread.currentThread().getName());
                    str.wait();
                    System.out.println("Waiting completion for thread " + Thread.currentThread().getName());
                }
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            System.out.println("Got the control for "+Thread.currentThread().getName());
            
        }
        
    }

}

我创建了这段代码来检查notify()如何从等待线程列表中选择一个线程以允许进一步执行。

现在我得到上述代码的以下输出

Created thread Thread-0
Created thread Thread-1
Created thread Thread-2
Sending in waiting state for thread Thread-0
Created thread Thread-3
Sending in waiting state for thread Thread-1
Created thread Thread-4
Sending in waiting state for thread Thread-2
Sending in waiting state for thread Thread-3
Sending in waiting state for thread Thread-4
Waiting completion for thread Thread-0
Got the control for Thread-0

根据我的代码,我期望synchronized关键字应该锁定线程X的监视器对象,并且任何其他线程不应该被允许在它们自己的

RunnableImplTest
实例中进入该块,因为我已经在多个线程之间共享了监视器对象线程。

java multithreading synchronized
2个回答
0
投票

wait()
方法放弃线程在该对象上持有的锁。

来自

Object#wait(long,int)

此方法导致当前线程(此处称为 T)将自身置于该对象的等待集中,然后放弃该对象上的所有同步声明。


0
投票

这在 JavaDoc 中记录了 Object.wait()(注意添加了强调):

此方法导致当前线程(此处称为 T)将自身置于该对象的等待集中,然后 放弃该对象上的所有同步声明。

请注意,这是必需的:否则主线程如何执行

synchronized (testString) { testString.notify(); }
如果 

testString

 上的锁仍由您启动的任何线程持有。

顺便说一句,

testString

是一个可怕的名字:它不是一个字符串,它与测试没有任何关系,它分散了人们对其目的的理解。

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