[英]understanding how synchronized keyword works
在下面的代码中,我期望只有两个线程之一才能进入halt()
函数,然后暂停程序。 但是似乎两个线程都进入了synchronized
halt()函数。 为什么会这样呢?
package practice;
class NewThread implements Runnable {
String name; // name of thread
Thread t;
boolean suspendFlag;
NewThread(String threadname) {
name = threadname;
t = new Thread(this, name);
System.out.println("New thread: " + t);
suspendFlag = false;
t.start(); // Start the thread
}
// This is the entry point for thread.
public void run() {
try {
for(int i = 15; i > 0; i--) {
System.out.println(name + ": " + i);
Thread.sleep(200);
Runtime r = Runtime.getRuntime();
halt();
}
} catch (InterruptedException e) {
System.out.println(name + " interrupted.");
}
System.out.println(name + " exiting.");
}
synchronized void halt() throws InterruptedException
{
System.out.println(name + " entered synchronized halt");
Runtime r = Runtime.getRuntime();
Thread.sleep(1000);
r.halt(9);
System.out.println(name + " exiting synchronized halt"); // This should never execute
}
}
class Practice{
public static void main(String args[]) {
NewThread ob1 = new NewThread("One");
NewThread ob2 = new NewThread("Two");
// wait for threads to finish
try {
System.out.println("Waiting for threads to finish.");
ob1.t.join();
ob2.t.join();
} catch (InterruptedException e) {
System.out.println("Main thread Interrupted");
}
System.out.println("Main thread exiting."); // This should never execute
}
}
同步不锁定方法,而是锁定对象。
您只有一种方法,但是有两个对象。 每个线程锁定其自己的对象并调用halt()。
同步在每个对象上完成。 如果您有2个对象,则可能同时有2个线程进入halt()
方法。 您可以将方法设为静态以实现所需的功能。 通过将其设置为静态,将把锁放置在相应的Class
对象( NewThreadOne.class
)上,该对象关于NewThreadOne
的实例数是唯一的。
您已将2 objects
用于2 threads
作为其monitor lock
...。
因此,您的代码运行良好, 每个线程都访问其自己对象的锁以访问 halt()
方法。
在synchonized keyword
,您可以实现对象的锁定,线程可以通过该对象访问该类中的synchronized methods or atomic statements
。
synchronized
方法正在使用此方法进行锁定。 在您的情况下,您有2个不同的对象,因为您要构建2个线程实例,因此您不必锁定在同一对象上。 为了具有预期的同步行为,您需要使halt
方法为static
。
不建议在Java同步块中使用String对象作为锁,因为string是不可变的对象,并且文字字符串和实习字符串都存储在String池中。 因此,如果任何其他代码部分或任何第三方库使用相同的String作为那里的锁,那么即使它们完全不相关,它们都将被锁定在同一对象上,这可能会导致意外行为和不良性能。 建议不要在同步块上使用new Object()进行Java中的同步,而应使用String对象而不是String对象。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.