线程八锁学习
1、锁的东西就三个
对象和Class和自己定义的Object
2、锁的具体使用
这里用同步方法举例的
2.1 同一个类里面两个普通的 synchronized 方法
/** * * 这个类中的两个方法用的都是同一个锁 * */ public class WindowSell5 { public synchronized void sendMsg() throws InterruptedException{ TimeUnit.SECONDS.sleep(4); System.out.println("sendMsg"); } public synchronized void call(){ System.out.println("打电话"); } } /** * * 两个线程两个方法,先打印那个 先打印sendmsg 然后打印打电话。 * windowSell5 中的两个方法用的是同一个锁,锁是对象 * 两个锁谁先拿到谁执行。所以a线程先执行,即使说sendMsg 执行比较耗时,b线程也不会执行 * a线程和b线程用的是同一个锁,你用了我就不能用了,只有你释放了我才能拿到锁。所以说b线程一直会等待 * */ public class WindowSell5Test { public static void main(String[] args) throws InterruptedException{ WindowSell5 windowSell5 = new WindowSell5(); new Thread(()->{ try { windowSell5.sendMsg(); }catch (Exception e){ } },"a").start(); //如果这里不sleep 下 线程b也可能执行 TimeUnit.SECONDS.sleep(1); new Thread(()->{ windowSell5.call(); },"b").start(); } }
2.2同一个类里面一个synchronized 方法、一个普通的方法
/** * * 这个类中的一个方法有锁一个没有锁 * */ public class WindowSell1 { public synchronized void sendMsg() throws InterruptedException{ TimeUnit.SECONDS.sleep(4); System.out.println("sendMsg"); } public void hello(){ System.out.println("hello"); } } /** * 两个线程两个方法,先打印那个 打电话 * * a 线程执行后比较耗时4s,同时有把锁,锁 是 方法的调用者就是windowSell1 这个对象 * 而线程b 没有锁,不存在锁的争抢,b 线程一看,你忙着呢,我就不等你了我就执行了。 * * * * * * */ public class WindowSell1Test { public static void main(String[] args) throws Exception{ WindowSell1 windowSell1 = new WindowSell1(); new Thread(()->{ try { windowSell1.sendMsg(); }catch (Exception e){ } },"a").start(); TimeUnit.SECONDS.sleep(1); new Thread(()->{ windowSell1.hello(); },"b").start(); } }
2.3 同一个类里面两个用static 修饰的 synchronized 方法
public class WindowSell3 { public static synchronized void sendMsg() throws InterruptedException{ TimeUnit.SECONDS.sleep(4); System.out.println("sendMsg"); } public static synchronized void call(){ System.out.println("打电话"); } } /** * * WindowSell3 中的两个方法 sendMsg call 都有锁,有一个共同的锁,锁是WindowSell3 * 所以线程a 执行的时候,线程b需要等待 * * 即使说new 两个对象 一个执行 sendMsg 一个执行call 也是线程先打印 sendmsg 然后打印 打电话 * * * */ public class WindowSell3Test { public static void main(String[] args) throws InterruptedException{ WindowSell3 windowSell3 = new WindowSell3(); WindowSell3 windowSell3_1 = new WindowSell3(); new Thread(()->{ try { windowSell3.sendMsg(); }catch (InterruptedException i){ } },"a").start(); TimeUnit.SECONDS.sleep(1); new Thread(()->{ //windowSell3.call(); windowSell3_1.call(); },"b").start(); } }
2.4 同一个类里面一个用static 修饰的 synchronized 方法,一个不用static 修饰的 synchronized 方法
public class WindowSell4 { public static synchronized void sendMsg() throws InterruptedException{ TimeUnit.SECONDS.sleep(4); System.out.println("sendMsg"); } public synchronized void call(){ System.out.println("打电话"); } } /** * * * 两个线程两个方法,先打印那个 b线程 * WindowSell4 中的两个方法 sendMsg call 都有锁,sendMsg 这个方法的锁是类WindowSell4 * 而call 这个方法的锁是 对象,两个方法两把锁。 * 所以说 先打印 打电话 * */ public class WindowSell4Test { public static void main(String[] args) throws InterruptedException{ WindowSell4 windowSell4 = new WindowSell4(); new Thread(()->{ try { windowSell4.sendMsg(); }catch (Exception e){ } },"a").start(); //如果这里不sleep 下 线程b也可能执行 TimeUnit.SECONDS.sleep(1); new Thread(()->{ windowSell4.call(); },"b").start(); } }
3、同步代码块的使用
public class WindowSell5 { public void sendMsg(){ synchronized (WindowSell5.class){ try { TimeUnit.SECONDS.sleep(3); }catch (InterruptedException e){ } System.out.println("sendMsg"); } } public void call(){ synchronized (this){ try { TimeUnit.SECONDS.sleep(2); }catch (InterruptedException e){ } System.out.println("打电话"); } } public void hello(){ String s = "hello"; synchronized (s){ System.out.println("hello"); } } } public class MainTest1 { public static void main(String[] args) { WindowSell5 windowSell5 = new WindowSell5(); /** * * 1、hello 先执行,其次是call,其次是sendMsg * 2、三个不同的锁 */ new Thread(()->{ windowSell5.sendMsg(); },"a").start(); new Thread(()->{ windowSell5.call(); },"b").start(); new Thread(()->{ windowSell5.hello(); },"c").start(); } }