sy197661944 2011-09-16 09:47
浏览 230
已采纳

关于synchronized的问题.

此为 thinking in java 的一个例子.

如果一个线程类,在run方法里掉一个方法r(),对一个 int i 的变量做两次自加操作 , 有一个方法叫 getValue() , 取得int i的值.

main方法里,启动线程,同时一个死循环,一直取getValue();
如果getValue()取得的值是奇数则退出.

当对方法r()做 synchronized的时候,是会取得奇数的,
当且并当 getValue() 做 synchronized时,就取不到奇数了.

个人理解的 synchronized是监视器只能当前线程在执行synchronized的方法.(蹩脚的个人描述,但同网上的一个理解)

假定 A 为自增线程 ,B 为main线程.

猜测:情况 r()为 synchronized , getValue() 不为synchronized,
A自增了1次,切换到线程B,此时会取得奇数.
那么 synchronized 的方法执行时也是可以轮询到其他的线程的,这貌似也不违反并发的原则.因为另外一个线程并未执行此方法.
那为什么将 getValue() 设为 synchronized 时,就不会出现奇数的情况了呢?

帖代码:

[code="java"]

import java.util.Timer;
import java.util.TimerTask;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.atomic.AtomicInteger;

public class AtomicIntegerTest implements Runnable
{

private AtomicInteger ai = new AtomicInteger(0);
private Integer i = 0;

@Override
public void run()
{
    // this.ai.addAndGet(2);
    r();
}

private synchronized void r(){
    while (true)
    {
            this.i++;
            this.i++;
    }
}

public synchronized int getValue()
{
    // return ai.get();
        return i;
}

public static void main(String[] args)
{
    ExecutorService es = Executors.newCachedThreadPool();
    final AtomicIntegerTest ai = new AtomicIntegerTest();
    es.execute(ai);

    new Timer().schedule(new TimerTask()
    {
        @Override
        public void run()
        {
            System.out.println("close");
            //System.out.println(ai.getValue());
            System.exit(0);
        }
    }, 5000);

    int i;
    while (true)
    {
        i = ai.getValue();
        System.out.println("-" + i);
        if (i % 2 != 0)
        {
            System.out.println("--" + i);
            System.exit(0);
        }
        Thread.yield();
    }
}

}
[/code]

  • 写回答

5条回答 默认 最新

  • _1_1_7_ 2011-09-16 10:51
    关注

    public synchronized int getValue()
    private synchronized void r()

    两个方法都有synchronized 修饰符,对于同一个对象,这两个方法就不能并发执行,
    即每次只有一个线程调用其中的一个方法,所以就不会有奇数了

    本回答被题主选为最佳回答 , 对您是否有帮助呢?
    评论
查看更多回答(4条)

报告相同问题?

悬赏问题

  • ¥15 求差集那个函数有问题,有无佬可以解决
  • ¥15 【提问】基于Invest的水源涵养
  • ¥20 微信网友居然可以通过vx号找到我绑的手机号
  • ¥15 寻一个支付宝扫码远程授权登录的软件助手app
  • ¥15 解riccati方程组
  • ¥15 display:none;样式在嵌套结构中的已设置了display样式的元素上不起作用?
  • ¥15 使用rabbitMQ 消息队列作为url源进行多线程爬取时,总有几个url没有处理的问题。
  • ¥15 Ubuntu在安装序列比对软件STAR时出现报错如何解决
  • ¥50 树莓派安卓APK系统签名
  • ¥65 汇编语言除法溢出问题