线程同步及练习

使用synchronized修饰的方法控制对类成员变量的访问

访问修饰符synchronized 返回类型 方法名(参数列表){......}

或者synchronized访问修饰符  返回类型  方法名(参数列表){......}

synchronized就是为当前的线程声明一把锁

代码演示如下:

 * @Description模拟用户网络购票--使用同步方法解决线程带来的数据不安全问题
 */
public class TicketThread implements Runnable{
    private int ticket=10;//记录车票总数
    private int num=0;//记录用户抢到了几张票
    private boolean flag=false;//代表票是否卖完
    //用户抢票
    public void run() {
        while (true) {
            sale();
        }
    }
    public synchronized void sale(){
            //没有余票,跳出循环
            if (ticket<=0){
                flag=true;
                return;
            }
            //有余票,则抢票。第一步:修改车票数:总票数再抢完票后减一张,用户抢到票了,抢票数+1
            ticket--;
            num++;
            //模拟网络延迟
            try {
                Thread.sleep(500);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            //第二步:显示出票反馈给用户
            System.out.println(Thread.currentThread().getName()+"抢到了第"+num+"张票,剩余"+ticket+"张票");
        }


    public static void main(String[] args) {
        Runnable runnable=new TicketThread();
        Thread t1=new Thread(runnable,"淘票票");
        Thread t2=new Thread(runnable,"快手张");
        Thread t3=new Thread(runnable,"黄牛党");
        System.out.println("*******各方开始抢票******");
        t1.start();
        t2.start();
        t3.start();
    }
}

使用synchronized关键字修饰的代码块

synchronized(syncObject){

           //需要同步的代码

}

syncObject为需同步的对象,通常为this

效果与同步方法相同

 代码演示

 * @Description模拟用户网络购票--使用同步代码块解决线程带来的数据不安全问题
 */
public class TicketThread implements Runnable{
    private int ticket=10;//记录车票总数
    private int num=0;//记录用户抢到了几张票
    private boolean flag=false;//代表票是否卖完
    //用户抢票
    public void run() {
        while (true) {
            synchronized (this) {

                //没有余票,跳出循环
                if (ticket <= 0) {
                    break;
                }
                //有余票,则抢票。第一步:修改车票数:总票数再抢完票后减一张,用户抢到票了,抢票数+1
                ticket--;
                num++;
                //模拟网络延迟
                try {
                    Thread.sleep(500);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
                //第二步:显示出票反馈给用户
                System.out.println(Thread.currentThread().getName() + "抢到了第" + num + "张票,剩余" + ticket + "张票");
            }
        }
    }


    public static void main(String[] args) {
        Runnable runnable=new TicketThread();
        Thread t1=new Thread(runnable,"淘票票");
        Thread t2=new Thread(runnable,"快手张");
        Thread t3=new Thread(runnable,"黄牛党");
        System.out.println("*******各方开始抢票******");
        t1.start();
        t2.start();
        t3.start();
    }
}

多个并发线程访问同一资源的同步代码块时

      同一个时刻只能有一个线程进入synchronized(this)同步代码块

      当一个线程访问一个synchronized(this)同步代码块时,其他synchronized(this)同步代码块同样被锁定

      当一个线程访问synchronized(this)同步代码块时,其他线程可以访问该资源的非synchronized(this)同步代码

 多线程共享数据:

        可能带来的问题:数据不安全

        原因:多线程共同操作数据时,引发的冲突(如延迟时,操作未全部完成等等)

        思考:同步方法、同步代码块(synchronized)

        线程同步:即各线程之间要有个先来后到,不能一窝蜂

        线程同步其实是“排队”:上锁,排队,一个一个来,不能同时操作。

习题:

代码演示

 * @Description模拟用户网络购票--使用同步代码块解决线程带来的数据不安全问题
 */
public class TicketThread implements Runnable{
    private int ticket=10;//记录车票总数
    private int num=0;//记录用户抢到了几张票
    private boolean flag=false;//(1)代表票是否卖完(2)代表线程是否结束,flag:true,线程结束
    //用户抢票
    public void run() {
        while (!flag) {
            synchronized (this) {
                //没有余票,跳出循环
                if (ticket <= 0) {
                    break;
                }
                //有余票,则抢票。第一步:修改车票数:总票数再抢完票后减一张,用户抢到票了,抢票数+1
                ticket--;
                num++;
                //模拟网络延迟
                try {
                    Thread.sleep(500);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
                //第二步:显示出票反馈给用户
                System.out.println(Thread.currentThread().getName() + "抢到了第" + num + "张票,剩余" + ticket + "张票");
                //判断当前线程名称是否为黄牛党,如果是线程结束,保证买一张票
                if (Thread.currentThread().getName().equals("黄牛党")){
                      flag=true;
                }else{
                      flag=false;
                }
            }
        }
    }


    public static void main(String[] args) {
        Runnable runnable=new TicketThread();
        Thread t1=new Thread(runnable,"淘票票");
        Thread t2=new Thread(runnable,"快手张");
        Thread t3=new Thread(runnable,"黄牛党");
        System.out.println("*******各方开始抢票******");
        t1.start();
        t2.start();
        t3.start();
    }
}

习题:

 代码演示

public class RunThread implements Runnable {
    //多个选手(多个线程)共同跑一千米
    private int meters = 1000;

    //实现一个选手拿到接力棒跑100米的过程
    public void run() {
        while (true) {
            //同步代码块保证了在跑选手只有一人
            synchronized (this) {
                if (meters < 100) {
                    break;
                }
                //一个人拿到接力棒跑完100米
                System.out.println(Thread.currentThread().getName() + "拿到了接力棒");
                for (int i = 10; i <= 100; i += 10) {
                    try {
                        Thread.sleep(100);
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }
                    System.out.println(Thread.currentThread().getName() + "跑了" + i + "米");
                }
                //剩余的路途就减少一百米
                meters -= 100;
            }
            try {
                Thread.sleep(1000);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }
    }
     //模拟几个选手参加接力赛
    public static void main(String[] args) {
       Runnable runnable=new RunThread();
        Thread person1=new Thread(runnable,"选手赵");
        Thread person2=new Thread(runnable,"选手钱");
        Thread person3=new Thread(runnable,"选手孙");
        Thread person4=new Thread(runnable,"选手李");
        Thread person5=new Thread(runnable,"选手周");
        person1.start();
        person2.start();
        person3.start();
        person4.start();
        person5.start();
    }
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值