java - 无法理解java中的同步块(synchronized block)

标签 java multithreading synchronization

我正在尝试研究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 mainobj 对象中来执行相同操作时,它显示不同的输出。

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/

相关文章:

java - 如何使在 Java 中阻塞的函数超时?

macos - 如何在多台 Mac 上同步您的 MAMP 安装

java - 如何在多线程上运行java程序

java - 在 graphql 模式中使用日期类型

java - 如何使用Netbeans GUI设计从JTable隐藏标题?

java - ArrayList Hash Map 提取并存储到 arraylist

multithreading - Rust 中的后台工作线程和同步

java - 如何映射已在 ORACLE 中创建但在 Hibernate 实体中创建的 "CREATE UNIQUE INDEX"

C++ boost 线程 : Passing a method of an object

Java 等待线程完成