14、线程同步机制
线程同步机制
1、同一个进程的多个线程共享同一块存储空间,带来了方便,也有冲突,为了保证数据在方法中被访问的正确性,在访问时加锁机制,synchronized,当一个线程获得对象的排他锁,独占资源,其他线程必须等待使用后释放;
问题:
1、一个线程持有锁,会导致其他的需要此锁的线程挂起;
2、多线程竞争下,加锁,释放,会导致上下文切换,和调度延时,引起性能问题;
3、如果一个优先级高的线程,等待一个优先级低的线程释放锁,会导致优先级倒置,引起性能问题;
线程同步安全
package com.syn; public class UnsafeBank { public static void main(String[] args) { Account account = new Account(8000,"ICBC_Bank"); Drawring accountDrawrer1 = new Drawring(account,5000,"liwang1"); Drawring accountDrawrer2 = new Drawring(account,5000,"liwang2"); accountDrawrer1.start(); accountDrawrer2.start(); } } //账户类 class Account{ int accountBalance;//余额 String AccountName;//卡名 //构造方法,类名一致 public Account(int accountBalance, String AccountName) { this.accountBalance = accountBalance; this.AccountName = AccountName; } } //银行取钱 class Drawring extends Thread{ Account accountinfo;//Account类定义账户信息 int drawringmoney;//取钱金额 int nowmoney;//现在拥有的钱 private Object Account; //构造方法 public Drawring(Account account, int drawringmoney, String name) { super(name); this.accountinfo = account; this.drawringmoney = drawringmoney; } //重写run方法 @Override public void run() { //同步代码块 synchronized (accountinfo){ //取钱 if(accountinfo.accountBalance-drawringmoney<0){ //输出信息 System.out.println(Thread.currentThread().getName()+":余额不足"); return; } try{ Thread.sleep(1000); }catch (Exception e){ e.printStackTrace(); } //卡内余额 accountinfo.accountBalance=accountinfo.accountBalance-drawringmoney; //拥有余额 nowmoney=nowmoney+drawringmoney; //打印账户余额 System.out.println(accountinfo+" 余额:"+accountinfo.accountBalance); //打印拥有的钱 //Thread.currentThread().getName() = this.getName(); System.out.println(this.getName()+"拥有的钱:"+nowmoney); } } }
package com.syn; import java.util.ArrayList; import java.util.List; import java.util.concurrent.CopyOnWriteArrayList; public class safeList { public static void main(String[] args) { CopyOnWriteArrayList<String> list = new CopyOnWriteArrayList<String>(); //List<String> list = new ArrayList<String>(); for (int i=0;i<10000;i++){ new Thread(()->{ list.add(Thread.currentThread().getName()); }).start(); } try{ Thread.sleep(2000); }catch (Exception e){ e.printStackTrace(); } System.out.println(list.size()); } }