【问题标题】:Java multithreading not thread-safe using synchronizedJava多线程使用同步不是线程安全的
【发布时间】:2012-11-22 17:53:38
【问题描述】:

一个简单的同步多线程测试。我想如果它是“同步的”,其他线程会等待。我错过了什么?

public class MultithreadingCounter implements Runnable {

    static int count = 0;

    public static void main(String[] args) {
        int numThreads = 4;
        Thread[] threads = new Thread[numThreads];

        for (int i = 0; i < numThreads; i++)
            threads[i] = new Thread(new MultithreadingCounter(), i + "");

        for (int i = 0; i < numThreads; i++)
            threads[i].start();

        for (int i = 0; i < numThreads; i++)
            try {
                threads[i].join();
            } catch (Exception e) {
                e.printStackTrace();
            }
    }           

    @Override
    public void run() {
        increment();
    }

    public synchronized void increment(){
            System.out.print(Thread.currentThread().getName() + ": " + count + "\t");
            count++; // if I put this first or increment it directly in the print line, it works fine.
    }
}

我认为这会显示如下内容:

0: 1    2: 0    1: 2    3: 3    

但它的实际输出:

0: 0    2: 0    1: 0    3: 3    

和其他类似的变体。它应该不按顺序显示每个增量(即 0,1,2,3)...

【问题讨论】:

    标签: java multithreading runnable


    【解决方案1】:

    您的 synchronized 关键字位于实例方法上。没有两个线程可以同时执行一个线程对象的这个方法。但是,这不是您的代码所做的。每个线程在自己的实例上执行该方法。同步并没有按照您的意图进行。如果它是一个static 方法,它会。

    【讨论】:

    • 会让static(与synchronized结合)充分地控制它,还是应该把变量volatile也做成?
    • (正确)同步就足够了。它已经确保增量与后续读取具有发生前的关系,这就是 volatile 将添加的所有内容。
    【解决方案2】:

    您的increment 方法应该是static

    public static synchronized void increment() {
    

    现在,每个对象都在单个实例上同步,但由于 count 是一个静态变量,您应该在 Class 对象本身上进行同步。

    【讨论】:

    • 我是让你获得 3000 声望的人,耶 :D
    【解决方案3】:

    当在方法之前使用同步关键字时,它确保该方法一次只能由一个线程执行,仅针对该对象。它不能确保其他对象的线程安全。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2011-09-16
      • 1970-01-01
      • 2016-03-12
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多