java - 如何在线程之间共享一个对象来证明它不是线程安全的?

标签 java multithreading

MutableInteger被视为线程安全类,因为从不同线程调用时它通常可能返回过时的值。

class MutableInteger{
    private int value;

    public int get(){
       return value;
    }

    public void set(int value){
       this.value=value;
    }   
}

这是我的线程实现:- 有一个主线程(主方法),并从中调用 MyThread。

class MyThread extends Thread{
    private int num;

    public void set(int num){
      this.num=num;
    }

    public void run(){
      MutableInteger mi=new MutableInteger();
      mi.set(num);
      System.out.println("Mythread "+mi.get());
    }
}

class MutableIntegerTest{
    public static void main(String[] args){
    MyThread t1=new MyThread();
    t1.set(10);     
    t1.start();
    MutableInteger mi=new MutableInteger();
    mi.set(99);
    System.out.println("Main thread" +mi.get());
    }
   }

现在这是我无法理解的地方。为了访问状态变量 value,我们需要使用 MutableInteger 类的 getter 和 setter 方法,因此对于每次访问,我们都需要实例化 MutableInteger 类。现在根据理论,每个对象都有自己的实例变量副本。在我的实现中,两个线程仅通过 MutableInteger 实例访问 value 变量。在我的例子中,value 不在线程之间共享,从而使我的 MutableInteger 线程安全。

我应该怎样做才能使线程共享?我是否应该公开该对象,以便可以在两个线程中使用相同的对象?但这不会将该对象公开给所有可用的类和线程吗?

我做错了什么吗?

最佳答案

如果您想测试您的 MutableInteger 以亲眼看看它不是线程安全的,则必须在线程之间共享一个对象。如果每个线程创建自己的 MutableInteger 实例,那么正如您所注意到的,您实际上并没有测试该特定事物,因为它只能由创建它的单个线程访问。

因此您需要创建一个实例,并让两个线程都使用它。例如:

可运行的对象(最好使用扩展Thread的类):

class MutableIntegerTester implements Runnable {

    private int num;
    private MutableInteger mutableInteger;

    public MutableIntegerTester(int num, MutableInteger mutableInteger) {
        this.num = num;
        this.mutableInteger = mutableInteger;
    }

    @Override
    public void run() {

        for ( int i = 0; i < 1000; i++ ) {
            mutableInteger.set(mutableInteger.get() + num);
        }
        System.out.println(mutableInteger.get());
    }

}

请注意,我将 run 方法更改为可以让您更好地看到安全性缺乏的地方。您既有非原子读取和添加,也有“陈旧”(非 volatile )变量的使用。

要共享对象,请使用:

public static void main(String[] args) {
    MutableInteger sharedObject = new MutableInteger();
    MutableIntegerTester tester1 = new MutableIntegerTester(10, sharedObject);
    MutableIntegerTester tester2 = new MutableIntegerTester(99, sharedObject);
    new Thread(tester1).start();
    new Thread(tester2).start();
}

现在,如果 mutableInteger 是线程安全的,您会期望结果始终打印 109000。但当然不会。每次运行它可能会打印不同的数字,有时甚至会为不同的线程打印不同的数字。

关于java - 如何在线程之间共享一个对象来证明它不是线程安全的?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/32583520/

相关文章:

java - Gradle:将多项目依赖项压缩到应用程序JAR文件中?

java - Java中 'throws'语句的用途是什么?

java - 为什么并发修改共享对象的所有方法不需要同步修饰符?

c++ - 正确关闭boost线程

java - 使用 Executor 框架在 Weblogic SOAP Webservice 中创建后台线程

java - 需要java中HashTable的内部实现

java - Java Socket InputStream读取数据,但返回顺序错误

c - pthread_join() 混合线程输出

multithreading - 使用 ThreadPool.GetAvailableThreads 来限制服务执行的工作量是否可以接受?

java - 如何创建一个基本的 Java 服务器?