Java 中的原始数据类型是线程安全的吗

发布于 2025-01-05 16:15:51 字数 1160 浏览 1 评论 0原文

原始数据类型是像 int & 吗? Java中的short线程安全?我执行了以下代码,有时看不到预期结果 500。

public class SampleThree extends Thread
{
    static long wakeUpTime = System.currentTimeMillis() + (1000*20);
    static int inT;
    public static void main(String args[])
    {
        System.out.println("initial:" + inT);
        for(int i=0; i<500; i++)
            new SampleThree().start();
        try {
            Thread.sleep(wakeUpTime - System.currentTimeMillis() + (1000*30));
            System.out.println("o/p:" + inT);
        }
        catch(Exception e){
            e.printStackTrace();
        }
    }

    public void run()
    {
        try {
            long s = wakeUpTime - System.currentTimeMillis();
            System.out.println("will sleep ms: " + s);
            Thread.sleep(s);
            inT++; // System.out.println(inT);
        }
        catch(Exception e) {
            e.printStackTrace();
        }
    }
}

这里并发500个线程将更新int变量inT。主线程等待并发更新完成后,打印inT值。

此处查找类似示例

Are the primitive data types like int & short thread-safe in Java? I have executed the following code and couldn't see expected result 500 some times.

public class SampleThree extends Thread
{
    static long wakeUpTime = System.currentTimeMillis() + (1000*20);
    static int inT;
    public static void main(String args[])
    {
        System.out.println("initial:" + inT);
        for(int i=0; i<500; i++)
            new SampleThree().start();
        try {
            Thread.sleep(wakeUpTime - System.currentTimeMillis() + (1000*30));
            System.out.println("o/p:" + inT);
        }
        catch(Exception e){
            e.printStackTrace();
        }
    }

    public void run()
    {
        try {
            long s = wakeUpTime - System.currentTimeMillis();
            System.out.println("will sleep ms: " + s);
            Thread.sleep(s);
            inT++; // System.out.println(inT);
        }
        catch(Exception e) {
            e.printStackTrace();
        }
    }
}

Here concurrently 500 thread will update the int variable inT. Main thread after waiting for concurrent update to be completed, prints inT value.

Find similar example here

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(4

稀香 2025-01-12 16:15:51

它们在三种情况下是不安全的:

  • longdouble 甚至不能保证原子更新(您可以看到来自不同线程的写入的一半) )
  • Java 内存模型 并不保证您会看到来自一个线程的最新更新在另一个线程中,没有某种额外的内存屏障
  • 无论如何,递增变量的行为都不是原子的

使用 AtomicInteger 等用于线程安全操作。

There are three ways in which they're not safe:

  • long and double aren't even guaranteed to be updated atomically (you could see half of a write from a different thread)
  • The Java Memory Model doesn't guarantee that you'll see the latest updates from one thread in another thread, without extra memory barriers of some kind
  • The act of incrementing a variable isn't atomic anyway

Use AtomicInteger etc for thread-safe operations.

孤独患者 2025-01-12 16:15:51

原始类型不是线程安全的。查看教程。

Primitive types are not thread safe. Check this tutorial.

独孤求败 2025-01-12 16:15:51

我建议使用 java.util.concurrent.atomic 中的类。它们是为线程安全而设计的,在某些情况下,JVM 可以利用硬件功能进行优化。

I would suggest using classes in java.util.concurrent.atomic. They are designed for thread-safety and in some cases the JVM can take advantage of hardware features to optimize.

眼藏柔 2025-01-12 16:15:51
  1. 要在多线程环境中读取/写入值,程序应该具有适当的同步或锁定以防止数据竞争。它与访问哪种数据类型无关。在理想的世界中,我们应该不共享任何内容或只共享不可变对象,这始终是线程安全的。

  2. 理论上,根据https://docs.oracle.com/javase/specs/jls/se8/html/jls-17.html#jls-17.7
    然而,实现倾向于原子性,下面的代码在我的环境中(64位ubuntu 18.04,Intel 64位CPU,Oracle JDK 8)打印出任何带或不带易失性关键字的内容,所以在这种情况下它是原子的,我想这适用于所有英特尔/AMD 64 CPU。
    我们也可以对 double 做同样的事情,尽管构造带有某些属性来检查的 double 值有点棘手。

public class LongThreadSafe {

    // multiple threads read and write this value.
    // according to the java spec, only volatile long is guaranteed to be atomic
    private static long value = 0;

    private static final int max = (1 << 30) - 1;
    private static final int threadCount = 4;
    static ExecutorService executorService = Executors.newFixedThreadPool(threadCount);

    static CyclicBarrier barrier = new CyclicBarrier(threadCount);

    public static void main(String[] args) throws InterruptedException {

        for (int i = 0; i < threadCount; i++) {
            executorService.submit(() -> {
                try {
                    // all threads start to work at the same time
                    barrier.await();
                } catch (Exception e) {
                    e.printStackTrace();
                }

                for (int j = 1; j < max; j++) {
                    // read value into v2
                    long v2 = value;
                    // check v2 
                    int low = (int) v2;
                    int high = (int) (v2 >> 32);
                    if ((high << 1) != low) {
                        System.out.println("invalid number found high=" + high + ", low=" + low);
                    }
                    // write LongThreadSafe.value again 
                    LongThreadSafe.value = ((long) j << 32) | (long) (j << 1);


                }
            });
        }
        executorService.shutdown();
        executorService.awaitTermination(10, TimeUnit.MINUTES);
    }
}
  1. To read/write of a value in a multiple thread environment, the program should have proper synchronize or lock to prevent data races. It has nothing to do with which data type to access. In an ideal world, we should share nothing or only share immutable objects, which is always thread safe.

  2. In theory, It is even not ensured to be atomic for long/double according to https://docs.oracle.com/javase/specs/jls/se8/html/jls-17.html#jls-17.7
    HOWEVER, the implementation tends to atomic, the following code print out nothing with or without volatile keyword in my environment(64bit ubuntu 18.04, Intel 64bit CPU, Oracle JDK 8), so it is atomic in this situation, which I guess apply to all Intel/AMD 64 CPU.
    We could do the same for double as well, although it is a little tricky to construct double value with certain property to check.

public class LongThreadSafe {

    // multiple threads read and write this value.
    // according to the java spec, only volatile long is guaranteed to be atomic
    private static long value = 0;

    private static final int max = (1 << 30) - 1;
    private static final int threadCount = 4;
    static ExecutorService executorService = Executors.newFixedThreadPool(threadCount);

    static CyclicBarrier barrier = new CyclicBarrier(threadCount);

    public static void main(String[] args) throws InterruptedException {

        for (int i = 0; i < threadCount; i++) {
            executorService.submit(() -> {
                try {
                    // all threads start to work at the same time
                    barrier.await();
                } catch (Exception e) {
                    e.printStackTrace();
                }

                for (int j = 1; j < max; j++) {
                    // read value into v2
                    long v2 = value;
                    // check v2 
                    int low = (int) v2;
                    int high = (int) (v2 >> 32);
                    if ((high << 1) != low) {
                        System.out.println("invalid number found high=" + high + ", low=" + low);
                    }
                    // write LongThreadSafe.value again 
                    LongThreadSafe.value = ((long) j << 32) | (long) (j << 1);


                }
            });
        }
        executorService.shutdown();
        executorService.awaitTermination(10, TimeUnit.MINUTES);
    }
}
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文