java线程的结果不一致 [英] Inconsistent results with java threads

查看:135
本文介绍了java线程的结果不一致的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有一个实现runnable的线程类和一个int计数器作为实例变量。两个同步方法添加和子。当我以某种方式运行我的测试类时,它会在几次打印错误的结果。据我所知,当一个方法同步时,整个对象将被锁定以供其他线程访问,每当我们得到相同的结果时,这个逻辑是什么?有些情况并非如此。我错过了什么吗?

I have a thread class which implements runnable and an int counter as instance variable. Two synchronized methods add and sub. When I run my test class somehow it is printing wrong results once in couple of times. As far as I understand when a method is synchronized, entire object will be locked for accessing by other threads, with this logic every time we should get same results right? Some how that is not the case. Am I missing something?

我的机器是Windows 7,64位。

My machine is Windows 7, 64 bit.

 public class ThreadClass implements Runnable {

        int counter = 0;

        @Override
        public void run() {
            add();
            sub();
        }

        public synchronized void add() {
            System.out.println("ADD counter" + (counter = counter + 1));
        }

        public synchronized void sub() {
            System.out.println("SUB counter" + (counter = counter - 1));
        }
    }

Testclass

Testclass

public class ThreadTest {

    public static void main(String args[]) {
        ThreadClass tc = new ThreadClass();
        Thread tc0 = new Thread(tc);
        tc0.start();
        tc0.setPriority(Thread.MAX_PRIORITY);
        Thread tc1 = new Thread(tc);
        tc1.start();
        tc1.setPriority(Thread.NORM_PRIORITY);
        Thread tc2 = new Thread(tc);
        tc2.start();
        tc2.setPriority(Thread.MIN_PRIORITY);
    }
}

结果

ADD counter1
ADD counter2
SUB counter1
SUB counter0
ADD counter1
SUB counter0

注意:您可能需要进行几次运行才能产生这种不一致。

Note: You may need to do couple of runs to produce this inconsistency.

推荐答案

同步确实意味着所有线程都会阻止等待获取锁定,然后才能进入同步块。只有一个线程可以锁定对象,因此只有一个线程可以在 add() sub()方法。

Synchronization will indeed mean that all threads will block waiting to acquire a lock before they can enter the synchronized block. Only one thread can ever have the lock on the object, so only one thread can be in the add() or sub() methods.

但是,这并不意味着有关线程排序的任何其他内容。你开始三个线程 - 唯一的保证是他们不会通过运行 add sub 方法一次。线程1可以调用 add(),然后线程3可以调用 add(),然后线程2可以调用 add(),然后他们都可以调用 sub()。或者他们都可以调用 add()然后 sub()。或者任何混合 - 唯一的要求是每个线程在调用 sub()之前调用 add()并且没有两个线程将调用 add() sub(),而另一个线程在该方法中。

However, this does not imply anything else about the ordering of threads. You're starting three threads - the only guarantee is that they won't stomp on each other by running the add or sub methods at once. Thread 1 can call add(), then thread 3 can call add(), then thread 2 can call add(), then they can all call sub(). Or they could all call add() and then sub() each. Or any mixture - the only requirement being that each thread calls add() before it calls sub() and that no two threads will ever call add() or sub() while another thread is in that method.

除此之外:在某些情况下,它可能会在上同步,因为它是公开的 - 它通常是首选使用要锁定的内部私有对象,以便其他任何呼叫者都无法锁定并违反您设计的任何锁定策略。

Aside: it can be, in some cases, bad form to synchronize on this, as it's public - it's often preferred to use an internal private Object to lock on so that no other callers can take your lock and violate any locking strategies you have designed.

这篇关于java线程的结果不一致的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆