4.Java线程安全的问题

线程安全的问题出现的原因
1.存在两个或者两个以上的线程
2.共享着同一个资源并且执行语句是多句

** 解决方法 **

第一种 (同步块代码)
1.格式
      synchronized (锁对象){
                执行的语句
             }
2.锁对象可以是任意的对象 (必须是唯一的)
3.锁对象必须是共享的数据,不能为静态的成员变量
4.static或者常量池中属性
第二种(同步函数)
1.非静态的同步方法锁对象是----this对象(当前的对象)
2.静态的同步方法的锁对象是----当前类的claas文件 ===>(new Class)
           (当类的class文件加载进入到内存的时候,jvm会自动的生成对应的(Class)描述文件)

** 同步函数代码**

  //非静态的同步函数 ===>锁对象===> this对象
    @Override
    public synchronized void run() {
          System.out.println("非静态同步函数的实现");
      }
  //静态同步函数 ===> 锁对象===> 当前方法所属类的class文件对象
    public synchronized static  void saleTitck(){
      System.out.println("静态同步函数的实现");
    }
同步代码块和同步函数的区别
1.同步代码块的锁对象我们自己指定,同步函数是对象指定
 2.同步代码块可以随意指定那个范围被同步,同步函数必须是整个函数
 3.如果没有存在线程安全的问题就不需要使用同步代码块
 4.推荐使用同步代码块的使用

卖票的列子 (继承了Thread类)

/*
    卖票的例子:
        3个窗口同时买票的功能 同时卖50张票的功能
        出现了线程安全的问题:
        1.数据一定使用共享的数据使用static修饰
        2.同步代码块的锁对象也是静态的 static 或者常量池中的常量
 */
public class SaleTitick extends  Thread {
    public  SaleTitick(String name){
        super(name);
    }
    //共50张 这个要共享数据 定义为static
     static int titick = 50;
    //这个锁对象一定钥匙静态的,才可以统一的管理
     static  Object o = new Object();
    @Override
    public void run() {
        while (true){
            //同步的代码块的方式 锁对象是任何的对象,任何对象都内置了隐式的一个状态 这个状态就是记录锁的状态了
            synchronized ("锁"){
                if (titick>0){
                    System.out.println(Thread.currentThread().getName()+"卖出第"+titick+"张票");
                    titick--;
                }else{
                    System.out.println("票卖完了");
                    break;
                }
            }
        }
    }
    public static void main(String[] args) {
        SaleTitick saleTitick1 = new SaleTitick("窗口1");
        SaleTitick saleTitick2 = new SaleTitick("窗口2");
        SaleTitick saleTitick3 = new SaleTitick("窗口3");
        //调用start方法
        saleTitick1.start();
        saleTitick2.start();
        saleTitick3.start();
    }

}
卖票列子(实现 Runable接口)
/**

   需求:
     卖50张票的实现了Runable类
     
 */
public class SaleTitckRunable implements Runnable {
    static  int titck = 50; //静态数据共享
    static  Object o = new Object(); //锁对象共享
    @Override
    public void run() {
        while (true){
            //同步代码块的方法去实现这个功能
            synchronized (o){
                if (titck>0){
                    System.out.println(Thread.currentThread().getName()+":"+titck);
                    titck--;
                }else{
                    System.out.println("卖完了");
                    break;
                }
            }
        }
   }
    public static void main(String[] args) {
        SaleTitckRunable  runable = new SaleTitckRunable();
        SaleTitckRunable  runable1 = new SaleTitckRunable();
        SaleTitckRunable  runable2 = new SaleTitckRunable();
        Thread thread = new Thread(runable,"线程1");
        Thread thread1 = new Thread(runable1 ,"线程2");
        Thread thread2 = new Thread(runable2,"线程3");
        thread.start();
        thread1.start();
        thread2.start();
    }
}

死锁出现的现象 (两个线程都互相同步,你不让我我也不让你)

** 代码如下**

/**
    死锁出现的问题:
    需求:
       天气热,去办公室拿遥控和电池
       zhangsan先去拿遥控器,再去拿电池
       lisi先去拿电池,然后再去拿遥控器
 */
public class DeadLock  extends  Thread{
    public  DeadLock(String name){
        super(name);
    }
    //重写run方法

    @Override
    public void run() {

        while (true){
            if ("zhangsan".equals(this.getName())){
                synchronized ("遥控器"){
                    System.out.println(this.getName()+"拿到了遥控器,接下来去拿电池");
                }
                synchronized ("电池"){
                    System.out.println(this.getName()+"拿到了电池真开心");
                }
            }else if ("lisi".equals(this.getName())){
                synchronized ("电池"){
                    System.out.println(this.getName()+"拿到了电池,接下来去拿遥控器");
                }
                synchronized ("遥控器"){
                    System.out.println(this.getName()+"拿到了遥控器真开心");
                }
            }
        }
    }
    public static void main(String[] args) {
        DeadLock deadLock = new DeadLock("zhangsan");
        DeadLock deadLock1 = new DeadLock("lisi");
        deadLock.start();
        deadLock1.start();
    }
}

你可能感兴趣的:(4.Java线程安全的问题)