Java并发同步问题

问题描述 投票:2回答:1

任何人都可以解释为什么下面的代码会导致竞争条件,因为我使方法同步但对象级别锁定,我正在深入了解java并发。请解释一下,因为如果我使用类级别肯定会工作,我怀疑线程占用的锁是不同的。

/**
 * 
 */
package lession2.shared.object;

/**
 * @author so_what
 *
 */

class SharedClass {
    private static int sharedData;

    public synchronized   int getSharedData() {
        return sharedData;
    }

    public synchronized   void setSharedData(int sharedData) {

        SharedClass.sharedData = sharedData;
    }

}

//output of the program should be the distinct numbers
public class StaleDataExample extends Thread {
    static  SharedClass s1=new SharedClass();
    static  int counter=0;
    public static  void main(String args[]) throws InterruptedException {

        StaleDataExample t1=new StaleDataExample();
        StaleDataExample t2=new StaleDataExample();
        StaleDataExample t3=new StaleDataExample();
        StaleDataExample t4=new StaleDataExample();
        StaleDataExample t5=new StaleDataExample();
        StaleDataExample t6=new StaleDataExample();
        t1.start();
        t2.start();
        t3.start();
        t4.start();

        t5.start();
        t6.start();
        t1.join();
        t2.join();
        t3.join();
        t4.join();
        t5.join();
        t6.join();
        System.out.println();

    }
    public void run()
    {

        s1.setSharedData(s1.getSharedData()+1); //read->modify->write operation
        System.out.print(s1.getSharedData()+" ");
    }

}
java multithreading synchronized
1个回答
2
投票

这里的问题是您没有以原子(例如同步)的方式递增共享值。

我们来看看以下几行:

s1.setSharedData(s1.getSharedData()+1)

首先,调用getSharedData,它是synchronized. You then increment the value, at callsetSharedData`来设置新值。问题是程序可以在get和set之间进行上下文切换。请考虑以下示例:

  1. 线程#1调用getSharedData(),得到0
  2. 线程#2调用getSharedData(),也获得0
  3. 线程#1将其值加1,并调用setSharedData(1)
  4. 线程#2还将其值加1,并调用setSharedData(1),而不是您期望的setSharedData(2)

解决此类问题的一种方法是不允许类'用户直接设置值,而是为它们提供一个原子递增值的方法:

class SharedClass {
    private static int sharedData;

    public synchronized int getSharedData() {
        return sharedData;
    }

    public synchronized void incrementSharedData(int amount) {
        sharedData += amount;
    }
}
© www.soinside.com 2019 - 2024. All rights reserved.