class Callme {
void call(String msg) {
System.out.print("[" + msg);
try {
Thread.sleep(10);
} catch (InterruptedException e) {
System.out.println("Interrupted");
}
System.out.println("]");
}
}
class Caller implements Runnable {
String msg;
Callme target;
Thread t;
public Caller(Callme targ, String s) {
target = targ;
msg = s;
t = new Thread(this);
t.start();
System.out.println("rahul");
System.out.println("rahul");
System.out.println("rahul");
System.out.println("rahul");
System.out.println("rahul");
System.out.println("rahul");
System.out.println("rahul");
System.out.println("rahul");
System.out.println("rahul");
System.out.println("rahul");
}
// synchronize calls to call()
public void run() {
synchronized(target) { // synchronized block
target.call(msg);
}
}
}
class Synch {
public static void main(String args[]) {
Callme target = new Callme();
Caller ob1 = new Caller(target, "Hello");
Caller ob2 = new Caller(target, "Synchronized");
Caller ob3 = new Caller(target, "World");
// wait for threads to end
try {
ob1.t.join();
ob2.t.join();
ob3.t.join();
} catch(InterruptedException e) {
System.out.println("Interrupted");
}
}
}
在这个程序中,当我使用没有System.out.print(“rahul”)的同步块时,它打印出完美的输出但是当我把这些不必要的SOP声明(“rahul”)输出变得扭曲时为什么会发生而不是同步?
答案 0 :(得分:1)
我将假设System.out.println
消息导致您的3条Caller
消息更改顺序:
Caller ob1 = new Caller(target, "Hello");
Caller ob2 = new Caller(target, "Synchronized");
Caller ob3 = new Caller(target, "World");
这里没有保证订单。即使首先构造"Hello"
Caller
对象,也不意味着它的run()
方法实际上将首先被执行。每个线程内的synchronized
块仍然存在竞争。例如,可以先打印"World"
字符串。
通过添加一系列System.out.println("rahul");
次来电,听起来好像是影响了节目的播放时间。底层PrintStream
对象是同步的,因此它会影响其他线程中的锁定,即使它们锁定在另一个对象上也是如此。任何同步都会跨越内存屏障,这会导致线程之间的缓存刷新和内存复制,并且可能会影响它们的运行顺序,速度等。如果运行程序1000次,您会看到许多不同的输出组合。这就是竞争条件的本质 - 它们是不可预测的。
答案 1 :(得分:0)
每个人System.out.println()
都在内部同步,因此单个println()
来电的输出不会出现乱码。
但是,对println()
的多次调用没有同步。如果多个线程同时写入同一个打印流,则无法保证其消息的相对顺序。
如果您需要特定的订购,则必须自己同步线程。
答案 2 :(得分:0)
从构造函数中启动一个线程并将其实例传递给线程。调用者尚未完全构造,因此其成员变量可能尚未在run方法中初始化。
额外的println允许看到bug。
Runnables应该定义工作,调用代码应该处理线程。 Runnables不应该自己运行。
您还应同步最终变量。
class Caller implements Runnable {
final String msg;
final Callme target;
public Caller(Callme targ, String s) {
target = targ;
msg = s;
System.out.println("rahul");
System.out.println("rahul");
System.out.println("rahul");
System.out.println("rahul");
System.out.println("rahul");
System.out.println("rahul");
System.out.println("rahul");
System.out.println("rahul");
System.out.println("rahul");
System.out.println("rahul");
}
// synchronize calls to call()
public void run() {
synchronized(target) { // synchronized block
target.call(msg);
}
}
}
class Synch {
public static void main(String args[]) {
Callme target = new Callme();
Thread ob1 = new Thread(Caller(target, "Hello"));
Thread ob2 = new Thread(Caller(target, "Synchronized"));
Thread ob3 = new Thread(Caller(target, "World"));
obj1.start();
obj2.start();
obj3.start();
// wait for threads to end
try {
ob1.t.join();
ob2.t.join();
ob3.t.join();
} catch(InterruptedException e) {
System.out.println("Interrupted");
}
} }