多线程(3)—同步代码块

1.同步机制:
java任意类型的对象都有一个标志位该标志位有0、1两种状态,其开始状态为1,当某个状态执行了synchronized(object)语句后object对象的标志位变为0状态,直到执行完整个synchronized语句中的代码,该对象的标志位又变回1状态。
当一个线程执行到synchronized(object)语句块时,先检查object对象的标志位,若为0表示有另外的线程正在执行synchronized(object)语句块,那么这个线程将暂时阻塞,让出cpu资源,直到另外的线程执行完相关代码,并将对象的标志位重新变为1,则这个线程的阻塞就被取消,这个线程继续运行,这个线程将对象标志位变为0,以防其他线程进入到相关代码中。

2.实例:

  • 机票模拟程序:三个售票窗口一同售票

  • 线程安全问题存在的原因:由于线程在操作共享数据的过程,未执行完毕的情况下,另外的线程参与进来导致安全问题

  • 多线程开发线程安全问题:保证安全的关键就是代码的原子性,所谓原子性是指一个操作要不执行完,要不不执行,中途不可以中断,保持同步。

  • 解决方法:

    • 方法一:同步代码块synchronized(object){容易出现问题的代码…},其中object可以使任意类型的对象
    • 方法二:同步方法

3.代码

  • 实现接口——同步代码块
public class Test2 {

    public static void main(String[] args) {
        TicketWindow tw = new TicketWindow();
        Thread t1 = new Thread(tw);//窗口一
        Thread t2= new Thread(tw);//窗口二
        Thread t3 = new Thread(tw);//窗口三
        t1.start();//多线程
        t2.start();
        t3.start();
    }

}
//定义窗口类:实现接口-同步代码块
class TicketWindow implements Runnable{
    //一共2000张机票
    //private static int number = 10;
    int number = 10;//声明属性的修饰符没有同步的作用,所以这样声明属性和以上声明属性是一致的
    //private  int number = 10;//效果一样
    @Override
    public void run() {

        //循环打印输出出售机票
        while(true){
            //同步代码块,使用synchronized关键字保证其原子性,关键字synchronized的意思就是同步
            //this是对象锁
            synchronized(this){
            //判断是否还有机票
                if(number > 0){
                    //提示售票信息,Thread.currentThread().getName()获得相称的名字
                    System.out.println(Thread.currentThread().getName()+"在售第"+number+"机票");
                    number--;
                }else{
                    break;
                }

            }
            //一个线程执行完,立即休眠1秒钟,另一个线程会立即执行同步代码块
            //每隔一秒休眠一次
            try {
                Thread.sleep(1000);
            } catch (Exception e) {
                e.printStackTrace();
            }
            //非同步的代码

        }
    }

}
  • 继承父类–同步代码块
    • 1.实现同步保证线程安全,考虑使用同步机制,
    • 2.同步在实现多线程的两种方法:实现接口的方法线程锁可以使用this代表当前对象,继承父类的方法线程锁慎用this,因为在继承中new了多个对象
    • 3.使用同步代码块方法
public class Test3 {

    public static void main(String[] args) {
        Number2 n1 = new Number2();
        Number2 n2 = new Number2();
        Number2 n3 = new Number2();

        n1.setName("线程1");
        n2.setName("线程2");
        n3.setName("线程3");
        n1.start();
        n2.start();
        n3.start();
    }

}
//继承父类--同步代码块
class Number2 extends Thread{
    //创建根基类对象,此对象属于成员属性,每个对象都有的属性,必须使用静态修饰成共用的属性,才能实现锁的作用
    static Object obj = new Object();
    static int number = 20;//属性设置为静态,遮掩两个对象就可共用一个number属性
    @Override
    public void run() {
        //两件事:1.同步number数字输出并减减,2.数字减一
        while(true){
                synchronized (obj) {
                    if (number > 0) {
                        System.out.println("我是"
                                + Thread.currentThread().getName() + ":"
                                + number--);
                    } else {
                        break;
                    }
                }
        }
    }
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值