同步方法无法按预期工作 [英] Synchronized method does not work as expected

查看:82
本文介绍了同步方法无法按预期工作的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有一个由两个线程共享的变量。这两个线程将对它进行一些操作。我不知道为什么每次执行程序时sharedVar的结果都不同。

I have a variable which is shared by two threads. The two threads will do some operations on it. I don't know why the result of sharedVar is different every time I execute the program.

public class Main
{
    public static int sharedVar = 0;
    public static void main(String[] args) 
    {
        MyThread mt1 = new MyThread();
        MyThread mt2 = new MyThread();
        mt1.start();
        mt2.start();

        try
        {
            // wait for the threads
            mt1.join();
            mt2.join();
        }
        catch (InterruptedException e1)
        {
            e1.printStackTrace();
        }

        System.out.println(sharedInt); // I expect this value to be 20000, but it's not
    }
}

以下是MyThread类

The following is the class "MyThread"

public class MyThread extends Thread
{
    private int times = 10000;
    private synchronized void addOne()
    {
        for (int i = 0; i < times; ++i)
        {
            Main.sharedVar ++;
        }
    }

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

sharedVar的最终结果有时是13735,12508,或18793;但从来没有20000,这是我期望的结果。该计划的另一个有趣的事情是时间= 1000。我总是得到2000作为最终结果。

The final result of sharedVar sometimes are 13735, 12508, or 18793; but never 20000, which is the result I expect. Another interesting thing about the program is when times=1000. I always get 2000 as the final result.

任何人都可以解释这种现象吗?

Can anyone explain this phenomenon?

推荐答案

synchronized方法保护资源 this ,这意味着您的代码相当于:

A synchronized method protects the resource this that means that your code is equivalent to:

private void addOne()
{
    synchronized(this)
    {
        for (int i = 0; i < times; ++i)
        {
            Main.sharedVar ++;
        }
    }
}

但你有两个对象调用哪个 addOne 方法。这意味着 mt1.addOne for mt2.addOne 因此您没有公共同步资源。

But you have 2 objects for which addOne method is called. That means this for mt1.addOne is not the same than this for mt2.addOne and therefore you don't have a common resource of synchronization.

尝试更改yout addOne 代码:

Try changing yout addOne code to:

private void addOne()
{
    synchronized(MyThread.class)
    {
        for (int i = 0; i < times; ++i)
        {
            Main.sharedVar ++;
        }
    }
}

你会看到预期的行为。如下面的评论所示,最好使用与 MyThread.class 不同的对象进行同步,因为类对象可以从许多点访问,而其他代码很容易尝试使用相同的对象进行同步。

And you will observe the expected behaviour. As the comments below suggest, it is better to use a different object than MyThread.class for synchronization since class objects are accesible from many points and it is easy that other code may try to synchronize using the same object.

这篇关于同步方法无法按预期工作的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

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