26day

day26

线程同步方法(synchronized)

//同步方法
public synchronized void method(int args){}
//会影响效率
package com.wang.syn;

//不安全的取钱
public class UnSafeBank {
   public static void main(String[] args) {
       Account account = new Account(1000,"wangyan");
       Drawing you = new Drawing(account,50,"夏雨");
       Drawing she = new Drawing(account,100,"夏风");

       you.start();
       she.start();
  }
}

//账户
class Account{
   int money = 0;
   String name ;

   public Account(int money, String name) {
       this.money = money;
       this.name = name;
  }
}
//银行:模拟取款
class Drawing extends Thread{

   Account account;//取钱
   int drawingMoney;//取了多少钱
   int nowMoney;//剩了多少钱

   public Drawing(Account account,int drawingMoney,String name){
       super(name);
       this.account = account;
       this.drawingMoney = drawingMoney;

  }

   //取钱
   //synchronized默认锁的是this
   @Override
   public void run() {
       //锁的对象就是变化的量,需要增删改的对象
       synchronized (account){
           //判断有没有钱
           if (account.money-drawingMoney<0){
               System.out.println(Thread.currentThread().getName()+"账户余额不足");
               return;
          }
           //sleep放大问题的发生性
           try {
               Thread.sleep(1000);
          } catch (InterruptedException e) {
               e.printStackTrace();
          }

           //卡内余额 = 余额 - 你取得钱数
           account.money = account.money - drawingMoney;
           //你手里的钱
           nowMoney = nowMoney + drawingMoney;

           System.out.println(account.name+"余额为"+account.money);
           System.out.println(this.getName()+"取到了"+nowMoney);
      }
      }

}
package com.wang.syn;

//不安全的买票
public class UnSafeBuyTicket {
   public static void main(String[] args) {
       BuyTicket station = new BuyTicket();
       new Thread(station,"夏雨").start();
       new Thread(station,"夏风").start();
       new Thread(station,"夏明").start();
  }
}
class BuyTicket implements Runnable{

   private int ticketNums = 10;
   private boolean flag = true;//外部停止方式标志位

   @Override
   public void run() {
       while (flag){
           try {
               buy();
          } catch (InterruptedException e) {
               e.printStackTrace();
          }
      }
  }
   //synchronized 同步方法 锁的是this
   private synchronized void buy() throws InterruptedException {
       //判断是否有票
       if (ticketNums <= 0){
           flag = false;
           return;
      }
       //模拟延时
       Thread.sleep(100);
       //买票
       System.out.println(Thread.currentThread().getName()+"拿到"+ticketNums--+"张票");

  }
}
package com.wang.syn;

import java.util.ArrayList;

//线程不安全的集合
public class UnSafeList {
   public static void main(String[] args) {
       ArrayList<String> list = new ArrayList<String>();
       for (int i = 0; i < 10000; i++) {
           new Thread(()->{
               synchronized (list){
                   list.add(Thread.currentThread().getName());
              }

          }).start();
      }
       try {
           Thread.sleep(3000);
      } catch (InterruptedException e) {
           e.printStackTrace();
      }
       System.out.println(list.size());
  }
}

测试JUC安全类型的集合(CopyOnWriteArrayList)

package com.wang.syn;

import java.util.concurrent.CopyOnWriteArrayList;

//测试JUC安全类型的集合
public class TestJUC {
   public static void main(String[] args) {
       CopyOnWriteArrayList<String> list = new CopyOnWriteArrayList<String>();
       for (int i = 0; i < 10000; i++) {
           new Thread(()->{
               list.add(Thread.currentThread().getName());
          }).start();
      }
       try {
           Thread.sleep(1000);
      } catch (InterruptedException e) {
           e.printStackTrace();
      }
       System.out.println(list.size());
  }
}

死锁

  • 多个线程各自占有一些资源,并且互相等待其他线程占有的资源才能运行,而导致两个或多个线程都在等待对方释放资源,都停止执行的情况,某一块同步块同时拥有“两个以上对象的锁”时,就可能会发生“死锁”的问题

  • 产生死锁的四个必要条件:

    1. 互斥条件:一个资源每次只能被一个进程使用

    2. 请求与保持条件:一个进程因请求资源而阻塞时,对已获得的资源保持不放

    3. 不剥削条件:进程已获得的资源,在未使用完之前,不能强行剥削

    4. 循环等待条件:若干个进程之间形成的一种头尾相接的循环等待资源关系

package com.wang.thread;

//死锁:多个线程互相持有对方的资源,形成僵持
public class DeadLock {
   public static void main(String[] args) {

       Makeup girl1 = new Makeup(0,"夏雨");
       Makeup girl2 = new Makeup(0,"夏风");

       new Thread(girl1).start();
       new Thread(girl2).start();
  }
}
//口红
class Lipstick{

}
//镜子
class Mirror{

}
//化妆
class Makeup extends Thread{

   //需要的资源只有一份,用static来保证只有一份
   static Lipstick lipstick = new Lipstick();
   static Mirror mirror = new Mirror();

   int choice;//选择
   String girlName;//使用化妆品的人

   Makeup(int choice,String girlName){
       this.choice = choice;
       this.girlName = girlName;
  }

   @Override
   public void run() {
       //化妆
       try {
           makeup();
      } catch (Exception e) {
           e.printStackTrace();
      }
  }

   //化妆,互相持有对方的锁,需要拿到对方的资源
   private void makeup() throws Exception {
       if (choice==0){
           synchronized (lipstick){//获得口红的锁
               System.out.println(this.girlName+"获得口红的锁");
               Thread.sleep(1000);
          }
           synchronized (mirror) {//获得镜子的嗦
               System.out.println(this.girlName+"获得镜子的锁");
          }
      }else {
           synchronized (mirror){//获得镜子的锁
               System.out.println(this.girlName+"获得镜子的锁");
               Thread.sleep(2000);
          }
           synchronized (lipstick) {//获得口红的锁
               System.out.println(this.girlName+"获得口红的锁");
          }
      }
  }
}

Lock(锁)

synchronized和lock的对比

  • lock是显示锁(手动开启手动结束)synchronized是隐式锁,出了作用域自动释放

  • lock只有代码块锁,synchronized有代码块锁和方法锁

  • 使用lock锁,jvm将花费嘉绍的时间来调度线程,性能更好,并且具有更好的扩展性

  • 优先使用顺序:

    lock>同步代码块(已经进入了方法体,分配了相应的资源)>同步方法

ReentrantLock可重入锁

 

# day26
## 线程同步方法(synchronized)
```java//同步方法public synchronized void method(int args){}//会影响效率```
```javapackage com.wang.syn;
//不安全的取钱public class UnSafeBank {    public static void main(String[] args) {        Account account = new Account(1000,"wangyan");        Drawing you = new Drawing(account,50,"夏雨");        Drawing she = new Drawing(account,100,"夏风");
        you.start();        she.start();    }}
//账户class Account{    int money = 0;    String name ;
    public Account(int money, String name) {        this.money = money;        this.name = name;    }}//银行:模拟取款class Drawing extends Thread{
    Account account;//取钱    int drawingMoney;//取了多少钱    int nowMoney;//剩了多少钱
    public Drawing(Account account,int drawingMoney,String name){        super(name);        this.account = account;        this.drawingMoney = drawingMoney;
    }
    //取钱    //synchronized默认锁的是this    @Override    public void run() {        //锁的对象就是变化的量,需要增删改的对象        synchronized (account){            //判断有没有钱            if (account.money-drawingMoney<0){                System.out.println(Thread.currentThread().getName()+"账户余额不足");                return;            }            //sleep放大问题的发生性            try {                Thread.sleep(1000);            } catch (InterruptedException e) {                e.printStackTrace();            }
            //卡内余额  =  余额 - 你取得钱数            account.money = account.money - drawingMoney;            //你手里的钱            nowMoney = nowMoney + drawingMoney;
            System.out.println(account.name+"余额为"+account.money);            System.out.println(this.getName()+"取到了"+nowMoney);        }        }
}```
```javapackage com.wang.syn;
//不安全的买票public class UnSafeBuyTicket {    public static void main(String[] args) {        BuyTicket station = new BuyTicket();        new Thread(station,"夏雨").start();        new Thread(station,"夏风").start();        new Thread(station,"夏明").start();    }}class BuyTicket implements Runnable{
    private int ticketNums = 10;    private boolean flag = true;//外部停止方式标志位
    @Override    public void run() {        while (flag){            try {                buy();            } catch (InterruptedException e) {                e.printStackTrace();            }        }    }    //synchronized 同步方法 锁的是this    private synchronized void buy() throws InterruptedException {        //判断是否有票        if (ticketNums <= 0){            flag = false;            return;        }        //模拟延时        Thread.sleep(100);        //买票        System.out.println(Thread.currentThread().getName()+"拿到"+ticketNums--+"张票");
    }}```
```javapackage com.wang.syn;
import java.util.ArrayList;
//线程不安全的集合public class UnSafeList {    public static void main(String[] args) {        ArrayList<String> list = new ArrayList<String>();        for (int i = 0; i < 10000; i++) {            new Thread(()->{                synchronized (list){                    list.add(Thread.currentThread().getName());                }
            }).start();        }        try {            Thread.sleep(3000);        } catch (InterruptedException e) {            e.printStackTrace();        }        System.out.println(list.size());    }}```
测试JUC安全类型的集合(CopyOnWriteArrayList)
```javapackage com.wang.syn;
import java.util.concurrent.CopyOnWriteArrayList;
//测试JUC安全类型的集合public class TestJUC {    public static void main(String[] args) {        CopyOnWriteArrayList<String> list = new CopyOnWriteArrayList<String>();        for (int i = 0; i < 10000; i++) {            new Thread(()->{                list.add(Thread.currentThread().getName());            }).start();        }        try {            Thread.sleep(1000);        } catch (InterruptedException e) {            e.printStackTrace();        }        System.out.println(list.size());    }}```
## 死锁
- 多个线程各自占有一些资源,并且互相等待其他线程占有的资源才能运行,而导致两个或多个线程都在等待对方释放资源,都停止执行的情况,某一块同步块同时拥有“两个以上对象的锁”时,就可能会发生“死锁”的问题
- 产生死锁的四个必要条件:  1. 互斥条件:一个资源每次只能被一个进程使用  2. 请求与保持条件:一个进程因请求资源而阻塞时,对已获得的资源保持不放  3. 不剥削条件:进程已获得的资源,在未使用完之前,不能强行剥削  4. 循环等待条件:若干个进程之间形成的一种头尾相接的循环等待资源关系
```javapackage com.wang.thread;
//死锁:多个线程互相持有对方的资源,形成僵持public class DeadLock {    public static void main(String[] args) {
        Makeup girl1 = new Makeup(0,"夏雨");        Makeup girl2 = new Makeup(0,"夏风");
        new Thread(girl1).start();        new Thread(girl2).start();    }}//口红class Lipstick{
}//镜子class Mirror{
}//化妆class Makeup extends Thread{
    //需要的资源只有一份,用static来保证只有一份    static Lipstick lipstick = new Lipstick();    static Mirror mirror = new Mirror();
    int choice;//选择    String girlName;//使用化妆品的人
    Makeup(int choice,String girlName){        this.choice = choice;        this.girlName = girlName;    }
    @Override    public void run() {        //化妆        try {            makeup();        } catch (Exception e) {            e.printStackTrace();        }    }
    //化妆,互相持有对方的锁,需要拿到对方的资源    private void makeup() throws Exception {        if (choice==0){            synchronized (lipstick){//获得口红的锁                System.out.println(this.girlName+"获得口红的锁");                Thread.sleep(1000);            }            synchronized (mirror) {//获得镜子的嗦                System.out.println(this.girlName+"获得镜子的锁");            }        }else {            synchronized (mirror){//获得镜子的锁                System.out.println(this.girlName+"获得镜子的锁");                Thread.sleep(2000);            }            synchronized (lipstick) {//获得口红的锁                System.out.println(this.girlName+"获得口红的锁");            }        }    }}```
## Lock(锁)
synchronized和lock的对比
- lock是显示锁(手动开启手动结束)synchronized是隐式锁,出了作用域自动释放
- lock只有代码块锁,synchronized有代码块锁和方法锁
- 使用lock锁,jvm将花费嘉绍的时间来调度线程,性能更好,并且具有更好的扩展性
- 优先使用顺序:
  lock>同步代码块(已经进入了方法体,分配了相应的资源)>同步方法
***ReentrantLock可重入锁***

posted @ 2021-05-05 13:14  卧剑之鱼  阅读(78)  评论(0)    收藏  举报