Java多线程编程(2)线程安全与数据同步

2022-12-11  本文已影响0人  景知育德

数据同步

数据不一致

在上一篇文章的例子中,我们让四台叫号窗口,叫号1~50,但是运行的时候,可能会出现各种各样的“bug”,包括

synchronized

我们可以用synchronized关键词,来简单的、朴素的避免上述情况。它提供一种互斥机制,在同一个时刻,只能有一个线程访问同步资源。

这类似于厕所里的小隔间,一次只能进去一个人,里面的人出来,别人才能够继续进去。

交错使用synchronized来上锁,可能会出现死锁的风险。对于一些开源库,调用层次比较深,可能不能直观地看出来有死锁的风险。例如JDK自带的HashMap,不是线程安全的类,如果在多线程同时写入的情况下,就可能会发生死锁。

如果想用线程安全的map数据结构,可以用ConcurrentHashMap或者Collections.synchronizedMap来代替。

package org.example;

public class Study7Synchronized {
    public static void main(String[] args) {
        int size = 4;
        String[] chineseNums = {"甲", "乙", "丙", "丁"};
        SynTicketWindowRunnable runnable = new SynTicketWindowRunnable();
        Thread[] threads = new Thread[size];
        for (int i = 0; i < size; i++) {
            threads[i] = new Thread(runnable, "窗口" + chineseNums[i]);
        }
        for (int i = 0; i < size; i++) {
            threads[i].start();
        }

        System.out.println("启动各柜台完毕!");
    }
}

/**
 * 改进之后,不再使用static的index
 */
class SynTicketWindowRunnable implements Runnable {
    private static final int MAX = 500;
    private int index = 1;
    private static final Object MUTEX = new Object();

    @Override
    public void run() {
        while (index <= MAX){
            synchronized (MUTEX) {
                if (index <= MAX)
                    System.out.println(Thread.currentThread().getName() + ":" + (index++));
            }
        }
    }
}

如以上代码,我们在涉及修改index的地方加上了 synchronized,从而实现了同步。

上一篇 下一篇

猜你喜欢

热点阅读