java多线程

有道面试题是这样考的:

一个全局变量tally,两个线程并发执行(代码段都是ThreadProc),问两个线程都结束后,tally取值范围。

    inttally = 0;//glable

    void ThreadProc() {
        for(int i = 1;i <= 50;i++)
            tally += 1;
    }

答案是50-100,其实如果写个代码测试一下的话一直都是输出100,不过理论上是50-100无误,可能是计算机运行速度太快了吧,还没等线程挂起就运行完了,当把循环次数提高到10万以上级别的时候效果就很明显了,那为什么是50-100呢,其实是因为tally+=1在汇编里面不止一条语句,有可能在执行一条之后线程被挂起了,跳到另一个线程里面执行去了,然后就造成了数据出错。
tally+=1 ==> tally = tally + 1;
比如当1线程在计算完tally+1之后就被挂起了,没有赋值给tally。然后2线程获取了运行权,顺利执行完tally+=1,然后挂起轮到1线程执行,这时候1线程继续以前没完成的操作,即将结果赋值给tally,这时候虽然两个线程各执行了一次加一操作,实际上相当于只执行了一次,就会出现50+50!=100的结果。
那么如何避免这种现象呢。这就用到了java里面的synchronized.


public void test() throws InterruptedException {
        TestThread thread = new TestThread();

        new Thread(thread).start();
        new Thread(thread).start();
        Thread.sleep(1000);
        System.out.println(anInt);
    }

public class TestThread implements Runnable {

        @Override
        public void run() {
            for (int i = 0; i < 800000; ++i) {
                addCount();
            }
        }

        private synchronized void addCount() {
            anInt++;
        }
    }

加了synchronized关键字那就表示必须要等到这个函数执行完了才能进行线程切换,也就是说在执行这个函数的时候不允许线程切换。就可以达到并发控制的效果。

再看另一个问题,我们知道这份代码只适用于两个相同的线程。那么如果出现两个不同的线程需要对同一个数据进行访问时该如何同步呢。
答案就是将方法写到一个类中。看一下代码就都明白了。

public class Demo4 {
    public static void main(String[] args) {
        Demo4 demo4 = new Demo4();
        demo4.test();
    }

    private void test() {
        Shared shared = new Shared();
        new Thread(new ThreadDemo1(shared)).start();
        new Thread(new ThreadDemo2(shared)).start();
        try {
            Thread.sleep(3000);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        System.out.println(anInt);
    }

    private int anInt = 0;

    public class ThreadDemo2 implements Runnable {
        Shared shared;
        public ThreadDemo2(Shared shared) {
            this.shared = shared;
        }
        @Override
        public void run() {
            for (int i = 0; i < 500000; ++i)
                shared.dev();
        }
    }

    public class ThreadDemo1 implements Runnable {
        Shared shared;
        public ThreadDemo1(Shared shared) {
            this.shared = shared;
        }
        @Override
        public void run() {
            for (int i = 0; i < 500000; ++i)
                shared.inc();
        }
    }

    public class Shared {
        public synchronized void inc() {
            anInt++;
        }
        public synchronized void dev() {
            anInt--;
        }
    }
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值