• 多线程(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;
                        }
                    }
            }
        }
    }
  • 相关阅读:
    线程简介
    JDBC连接数据库遇到的“驱动程序无法通过使用安全套接字层(SSL)加密与 SQL Server 建立安全连接。
    项目开发中需要考虑的问题2
    JPA使用中遇到Caused by: org.hibernate.hql.internal.ast.QuerySyntaxException: XXX is not mapped
    ORA-01747: user.table.column, table.column 或列说明无效
    IDEA使用一套代码启动多个应用
    tomcat8.5部署管理控制台
    ubuntu16虚拟机迁移/移动/复制后无法上网
    centos7没有IP地址
    repmgr自动故障转移的参数配置
  • 原文地址:https://www.cnblogs.com/tengpengfei/p/10454001.html
Copyright © 2020-2023  润新知