java线程并发与同步

关于多线程与并发,多线程是指系统在轮流执行不同的方法,由于CPU速度太快,所以我们看起来是同步执行的,这就是所谓的线程并发;

线程并发时访问共享变量会引起数据不一致的问题,解决数据的不一致问题就需要用到线程同步。

此篇讲线程同步技术。

同步技术引出:

先来个程序测试不同步的情况:

class MyRunable implements Runnable{
    private  int ticket = 10;
    @Override
    public void run() {
        while (true){
          if (ticket > 0 ) {
                System.out.println(Thread.currentThread().getName()+":ticket="+ticket--);
                try {
                    Thread.sleep(1000);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }else {
                System.out.println("卖光了");
                break;
            }
        }
    }
}
public class A {
    public static void main(String[] args) throws InterruptedException {
        MyRunable r = new MyRunable();
        Thread t1 = new Thread(r,"线程1");
        Thread t2 = new Thread(r,"线程2");
        Thread t3 = new Thread(r,"线程3");
        Thread t4 = new Thread(r,"线程4");
        t1.start();
        t2.start();
        t3.start();
        t4.start();

    }
}

结果:可以看出卖票没有顺序的,而且把一张票卖给多个人,这肯定是不符合要求的。

线程2:ticket=10
线程3:ticket=9
线程1:ticket=8
线程4:ticket=7
线程2:ticket=6
线程4:ticket=6
线程3:ticket=4
线程1:ticket=5
线程1:ticket=3
线程2:ticket=2
线程3:ticket=3
线程4:ticket=1
卖光了
卖光了
卖光了
卖光了

为什么呢,1、run方法内的代码并不是同步执行完毕的,而是分时间段来执行的;

                      判断票数是否大于0,如果线程a判断大于0, 现在a挂起了,它之后会继续在其他时间片执行,现在线程b将票已经卖光了(ticket = 0),但是线程a获取了时间片,他会继续将0减1,结果可能就会出现-1的结果;

                   2、还有run方法中这句

System.out.println(Thread.currentThread().getName()+":ticket="+ticket--);

                 println是线程安全的,但是传入的ticket变量是在进行自减,自减其实是分为三步来完成的:

1.ticket = this.ticket 先取原值
2.ticket+1 再加法运算
3.ticket = ticket 再赋值

所以,以上程序在非并发情况下,可能产生一张票卖多个人,卖空票,这就不是我们需要的结果,因为需要线程的同步来实现。

修改run方法

public void run() {
            while (true) { 
                //同步代码块
                synchronized (this) {
                if (ticket > 0) {
                    try {
                        Thread.sleep(1000);
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }
                    System.out.println(Thread.currentThread().getName() + ":ticket=" + ticket--);
                } else {
                    System.out.println("卖光了");
                    break;
                }
            }
        }
    }

 

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值