同步方法和同步块(synchronized)
一、 同步方法
1. public synchronized void method(){}
synchronized 方法控制对 “对象” 的访问,每个对象对应一把锁,每个synchronized方法都必须获得调用该方法的对象锁才能执行。否则会导致阻塞。方法一旦执行,就独占该锁,直到该方法返回才释放锁,后面被阻塞的线程才能获得这个锁,继续执行。
2. 若将一个大方法申明为一个synchronized方法,将极大的影响效率。
二、同步块
1. synchronized(Obj){}
Obj(同步监视器)可以是任何对象,但推荐使用共享资源作为同步监视器。
同步方法中无需指定同步监视器,因为同步方法中的同步监视器就是this,就是这个对象本身,也可以是class。
2. 同步块的Obj就是被修改的对象 ,方法体的内容为:对这个对象的增删改 。
三、使用同步方法和同步块对三个不安全实例的优化。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 package demo.study.syn;public class UnsafeBuyTickets { public static void main (String[] args) { Buytickets station = new Buytickets(); new Thread(station,"小明" ).start(); new Thread(station,"小红" ).start(); new Thread(station,"黄牛" ).start(); } } class Buytickets implements Runnable { private int ticketNum = 10 ; boolean flag = true ; @Override public void run () { while (flag){ try { buy(); } catch (InterruptedException e) { e.printStackTrace(); } } } public synchronized void buy () throws InterruptedException { if (this .ticketNum<=0 ){ flag = false ; return ; } Thread.sleep(100 ); System.out.println(Thread.currentThread().getName()+"买到了" +ticketNum--); } }
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 package demo.study.syn;public class UnsafeBank { public static void main (String[] args) { Account account = new Account(1000 ,"中国银行" ); Drawing you = new Drawing(account,50 ,"you" ); Drawing girlFriend = new Drawing(account,100 ,"girlFriend" ); you.start(); girlFriend.start(); } } class Account { int money; String name; public Account (int money, String name) { this .money = money; this .name = name; } } class Drawing extends Thread { Account account; int drawMoney; int nowMoney; String name; public Drawing (Account account,int drawMoney,String name) { super (name); this .account=account; this .drawMoney=drawMoney; } @Override public void run () { synchronized (account){ if (account.money-drawMoney<0 ) { System.out.println(Thread.currentThread().getName()+"钱不够了" ); return ; } try { Thread.sleep(1000 ); } catch (InterruptedException e) { e.printStackTrace(); } account.money-=drawMoney; nowMoney+=drawMoney; System.out.println(Thread.currentThread().getName()+"手里的钱" +nowMoney); System.out.println(account.name+"卡内余额" +account.money); } } }
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 package demo.study.syn;import java.util.ArrayList;import java.util.List;public class UnsafeList { public static void main (String[] args) { List<String> list = new ArrayList<String>(); for (int i = 0 ; i < 10000 ; i++) { new Thread(()->{ synchronized (list) { list.add(Thread.currentThread().getName()); } }).start(); } System.out.println(list.size()); } }