我正在尝试研究java中的线程同步,并且我开始了解同步块(synchronized block)。我可能会问一个愚蠢的问题,因为我对线程同步不太了解,但在这个程序中我不理解 block 的行为。
class Table {
void printTable(int n) { //method not synchronized
for(int i=1; i<=10; i++) {
System.out.println(n + " * " + i + " = " + n*i);
try {
Thread.sleep(500);
} catch(Exception e) {
System.out.println(e);
}
}
System.out.println("Table of " + n + " is completed.");
}
}
class MyThread extends Thread {
Table t;
int num;
MyThread(Table t, int num) {
this.t = t;
this.num = num;
}
public void run() {
synchronized(t) {
t.printTable(num);
}
}
}
class TestSynchronization {
public static void main(String[] args) {
Table obj = new Table(); //only one object
MyThread t1;
MyThread t2;
t1 = new MyThread(obj, 10);
t2 = new MyThread(obj, 17);
t1.start();
t2.start();
}
}
它的输出是这样的:
10 * 1 = 10
10 * 2 = 20
10 * 3 = 30
10 * 4 = 40
10 * 5 = 50
Table of 10 is completed.
17 * 1 = 17
17 * 2 = 34
17 * 3 = 51
17 * 4 = 68
17 * 5 = 85
Table of 17 is completed.
这看起来是正确的,但是当我尝试通过从 run 方法中删除同步块(synchronized block)并将其应用到 void main
的 obj
对象中来执行相同操作时,它显示不同的输出。
class Table {
void printTable(int n) { //method not synchronized
for(int i=1; i<=5; i++) {
System.out.println(n + " * " + i + " = " + n*i);
try {
Thread.sleep(500);
} catch(Exception e) {
System.out.println(e);
}
}
System.out.println("Table of " + n + " is completed.");
}
}
class MyThread extends Thread {
Table t;
int num;
MyThread(Table t, int num) {
this.t = t;
this.num = num;
}
public void run() {
t.printTable(num);
}
}
class TestSynchronization {
public static void main(String[] args) {
Table obj = new Table(); //only one object
MyThread t1;
MyThread t2;
synchronized(obj) {
t1 = new MyThread(obj, 10);
t2 = new MyThread(obj, 17);
}
t1.start();
t2.start();
}
}
输出:
10 * 1 = 10
17 * 1 = 17
10 * 2 = 20
17 * 2 = 34
17 * 3 = 51
10 * 3 = 30
17 * 4 = 68
10 * 4 = 40
10 * 5 = 50
17 * 5 = 85
Table of 17 is completed.
Table of 10 is completed.
为什么这在第二种情况下不起作用,请解释一下。
如果可能的话,还建议我通过在 void main
中使用同步块(synchronized block)来获得相同输出的方法。
最佳答案
区别在于何处和何时对Table类的锁定
对象已获取。
在第一个示例中,Table 对象的锁是在 MyThread
类的实例内获取的。假设 MyThread 类的第一个实例获取表对象锁,则 MyThread 类的其他实例将无法获取表对象的锁,直到第一个实例释放它,也称为线程级同步 em>.
在第二个示例中,对象的锁是由驱动程序获取的,因此从技术上讲,此级别不存在并发问题,因为锁与驱动程序而不是单个线程相关联,这实际上是一种进程级同步。
关于java - 无法理解java中的同步块(synchronized block),我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/39825087/