Java线程同步问题

一、原子操作

        原子操作:不可中断的一个或者一系列操作, 也就是不会被线程调度机制打断的操作, 运行期间不会有任何的上下文切换。

        可以定义为原子操作的有:对于非long和double基本数据类型的"简单操作"都可以看作是原子的. 例如: 赋值和返回, 大多数体系中long和double都占据8个字节, 操作系统或者JVM很可能会将写入和读取操作分离为两个单独的32位的操作来执行, 这就产生了在一个读取和写入过程中一个上下文切换(context switch), 从而导致了不同任务线程看到不正确结果的的可能性。

二、线程同步问题

        举一个例子,我们写一个取票程序,在我们没有添加任何操作时,使用多个线程对同一个票数的数据进行修改。票数总数为100.

public void run(){
        for(int i=0;i<50;i++){
            try {
                Thread.sleep(10);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            System.out.println(Thread.currentThread().getName()+" 买到"+  tk.tick +"票...");
            tk.tick--;
        }
    }
public static void main(String[] args) {
        Ticket tk = new Ticket();
        UserThread ut = new UserThread(tk);
        Thread t1 = new Thread(ut);
        t1.setName("USER1");
        t1.start();
        Thread t2 = new Thread(ut);
        t2.setName("USER2");
        t2.start();
    }

        我们对其输出,可以看到结果为

         可以发现出现了两个人买了同一张票的情况,还有按序票有没有购买的情况。 

        这时我们就需要使用synchronized关键字或者自己上锁来避免线程同步问题。

        synchronized (监视器(锁)){

    }
        任何一个对象都是作为监视使用,但所有的线程必须使用同一个监视器。

        

public void run(){
        for(int i=0;i<50;i++){
            try {
                Thread.sleep(10);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            //继承类Thread时,使用tk,不能使用this,在使用接口时可以使用this
            synchronized (tk){
                System.out.println(Thread.currentThread().getName()+" 买到"+  tk.tick +"票...");
                tk.tick--;
            }
        }
    }
//使用synchronized方法也可以
public synchronized void mp(){
        System.out.println(Thread.currentThread().getName()+" 买到"+  tk.tick +"票...");
        tk.tick--;
    }
//或者对其进行主动上锁   
         try {
                //上锁
                lock.lock();
                System.out.println(Thread.currentThread().getName()+" 买到"+  tk.tick +"票...");
                tk.tick--;

            }finally {
                //释放锁
                lock.unlock();
            }

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值