在以下代码中,
public class Callme {
public Callme() {
// TODO Auto-generated constructor stub
}
void callA(String msg) throws InterruptedException
{
synchronized (this) {
System.out.print("["+msg);
Thread.sleep(1000);
}
System.out.println("]");
}
void callB(String msg) throws InterruptedException
{
synchronized (this) {
System.out.print("{"+msg);
Thread.sleep(1000);
}
System.out.println("}");
}
void callC(String msg) throws InterruptedException
{
synchronized (this) {
System.out.print("("+msg);
Thread.sleep(1000);
}
System.out.println(")");
}
}
其他地方:
public class Caller implements Runnable {
public char msg;
public Callme target;
public Thread t;
public Caller(char msg, Callme target) {
this.msg = msg;
this.target = target;
t= new Thread(this);
}
@Override
public void run() {
try {
switch (msg) {
case '[':
target.callA("Hello");
break;
case '{':
target.callB("Hello");
break;
case '(':
target.callC("Hello");
break;
default:
break;
}
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
其他地方:
Callme target = new Callme();
Caller ob1 = new Caller('[', target);
Caller ob2 = new Caller('{', target);
Caller ob3 = new Caller('(', target);
ob1.t.start();
ob2.t.start();
ob3.t.start();
假设callA
首先执行,在执行synchronized
语句后,在我的试用中,总是ob1
下一步执行。
我认为有时ob2
同步步骤应在此之前执行(至少有时)。
实际输出:
[Hello]
{Hello}
(Hello)
预期输出:
[Hello(Hello]
)
{Hello}
当然{,[
和(
的顺序可能会有所不同,并且无法预测。
答案 0 :(得分:1)
任何工作都不得征求
synchronized (this) {
<<job>>
}
<<after>>
任何作业必须在<<job>>
之前运行<<after>>
。
要被多个<<after>>
交错(不可能<<job>>
),必须至少阻止一个<<after>>
,直到后面的其他<<job>>
和<<after>>
被阻止为止被执行。使用代码的可能性很小(<<after>>
花时间打印一个字符,而<<job>>
花一秒钟)。
无论调用方法是多少,多少以及何时使用。
要产生所需的行为,必须在同步代码之后和blocking
代码之前添加<<after>>
。
class Call {
public Call() {}
private static void delay(int ms) {
try {
Thread.sleep(ms);
} catch (InterruptedException e) {
// keep out!
}
}
private void call(char a, String msg, char b) {
synchronized (this) {
System.out.print(a);
System.out.print(msg);
delay(100);
}
delay(ThreadLocalRandom.current().nextInt(10) * 10); // probability
System.out.println(b);
}
void callA(String msg) { call('[', msg, ']'); }
void callB(String msg) { call('{', msg, '}'); }
void callC(String msg) { call('(', msg, ')'); }
}
public class Callme {
static Call call = new Call();
static List<Consumer<String>> calls = asList(call::callA, call::callB, call::callC);
static void randomCall() {
calls.get(ThreadLocalRandom.current().nextInt(calls.size())).accept("Hello!");
}
public static void main(String... args) {
IntStream.range(0, 50).forEach(ignore -> new Thread(Callme::randomCall).start());
}
}
全无:
(Hello!)
(Hello!)
)
{Hello!{Hello!}
{Hello!}
}
[Hello!(Hello!]
)
(Hello![Hello!)
{Hello!]
(Hello!}
[Hello!)
[Hello!]
]
(Hello![Hello!)
(Hello!]
[Hello!)
...
答案 1 :(得分:0)
我会说预期的输出是
[Hello]
{Hello}
(Hello)
synchronized
块的锁,这些步骤需要时间Thread.start()
启动操作系统级别的线程(https://github.com/openjdk-mirror/jdk7u-jdk/blob/master/src/share/classes/java/lang/Thread.java#L673,https://github.com/openjdk-mirror/jdk7u-jdk/blob/master/src/share/classes/java/lang/Thread.java#L705,https://github.com/openjdk-mirror/jdk7u-jdk/blob/master/src/share/native/java/lang/Thread.c#L44,https://github.com/openjdk-mirror/jdk7u-hotspot/blob/master/src/share/vm/prims/jvm.cpp#L2634,https://github.com/openjdk-mirror/jdk7u-hotspot/blob/master/src/share/vm/runtime/thread.cpp#L420,链结尾为取决于系统的os::start_thread(thread);
行),因此最终取决于操作系统的是线程运行的速度和顺序,但是通常它们很快就会开始运行,并按照请求启动的顺序开始运行synchronized
使用对象监视器,它们建立了一个正在等待它们的线程的列表(https://github.com/openjdk-mirror/jdk7u-hotspot/blob/master/src/share/vm/runtime/objectMonitor.cpp#L186是文件,并且代码有点过时,但是列表本身是一个链表-好吧,是一个循环的,双向链接的链表-_waitSet
,通过从https://github.com/openjdk-mirror/jdk7u-hotspot/blob/master/src/share/vm/runtime/objectMonitor.cpp#L2251开始的添加/出队方法进行管理。因此notify()
和notifyAll()
遍历该列表并以确定的顺序唤醒其他线程。