java - synchronized(obj) 不起作用,为什么结果可以是 -1 或 0?

标签 java synchronized

synchronized(obj) 不行,为什么结果可以是-1或者0? 当我使用 synchronized(this) 时就可以了 那为什么会这样

public class RunnableSales {
    public static void main(String[] args) {
        Ticket1 t = new Ticket1();
        Thread t1 = new Thread(t);
        Thread t2 = new Thread(t);
        Thread t3 = new Thread(t);
        Thread t4 = new Thread(t);

        t1.start();
        t2.start();
        t3.start();
        t4.start();
    }
}

class Ticket1 implements Runnable {
    private int tick = 10;
    public void run() {
        Object obj = new Object();
        while (true) {
            synchronized (obj) {
                if (tick > 0) {
                    try {
                        Thread.sleep(10);
                    } catch (InterruptedException e) {
                    }
                    System.out.println(Thread.currentThread().getName() + "sale:" + tick--);
                } else {
                    break;
                }
            }
        }
    }
}

控制台打印是:

Thread-1sale:10
Thread-2sale:10
Thread-3sale:10
Thread-0sale:9
Thread-2sale:8
Thread-3sale:7
Thread-1sale:8
Thread-0sale:8
Thread-1sale:6
Thread-0sale:3
Thread-2sale:5
Thread-3sale:4
Thread-1sale:2
Thread-0sale:1
Thread-2sale:0
Thread-3sale:-1

synchronized(obj) 不行,为什么结果可以是-1或者0? 当我使用 synchronized(this) 时就可以了 那么为什么会这样

最佳答案

查看代码,发现每次调用run()都会生成一个新的Object obj,仅用于本次调用的同步。因此,实际上并没有进行同步。修复非常简单:将 Object obj 设为实例字段。您应该将其设置为 final 以禁止重新分配(这可能会干扰同步)。

固定版本看起来像这样:

public class Test {
    public static void main(String[] args) {
        Ticket1 t = new Ticket1(4);
        Thread t1 = new Thread(t);
        Thread t2 = new Thread(t);
        Thread t3 = new Thread(t);
        Thread t4 = new Thread(t);

        t1.start();
        t2.start();
        t3.start();
        t4.start();

        try{
            t1.join();
            t2.join();
            t3.join();
            t4.join();
        } catch (InterruptedException e){
        }
    }
}

class Ticket1 implements Runnable {
    private int tick = 10;
    private final Object obj = new Object();

    public void run() {
        while (true) {
            synchronized (obj) {
                if (tick > 0) {
                    try {
                        Thread.sleep(10);
                    } catch (InterruptedException e) {
                    }
                    System.out.println(Thread.currentThread().getName() + "sale:" + tick--);
                } else {
                    break;
                }
            }
        }
    }
}

我添加了代码以显式等待线程终止。您应该始终包含此代码以确保所有衍生线程在主线程退出之前完成。输出看起来像这样:

Thread-3sale:10
Thread-3sale:9
Thread-3sale:8
Thread-3sale:7
Thread-3sale:6
Thread-3sale:5
Thread-3sale:4
Thread-3sale:3
Thread-3sale:2
Thread-3sale:1

请注意,最终输出显示值 1。对于您的程序,这是正确的,因为在 tick 减少到 0 后没有输出。

关于java - synchronized(obj) 不起作用,为什么结果可以是 -1 或 0?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/49957056/

相关文章:

java - 如何在ConcurrentHashMap中基于getOrDefault()实现原子getOrDefaultWithPut()?

java - 在 Windows 命令行参数中使用空格

Java设计模式让sdk支持多种认证方案

java - 用于 Java 的 GAE : Mail API

java - 如何在不使用 this 的情况下在接口(interface)默认方法内进行同步?

java - 为什么这个synchronized block 好像要很久才能拿到锁?

java:同步方法效率低下

java - 如何使用 GeoTools 恢复内存中形状的特征?

java - 为什么在使用 JPA 执行基本 mySQL 搜索时会出现此错误?

java - 为什么同步方法不适用于多线程