Java多线程-线程的锁总结
一、多线程-同步函数的锁是this
/*
同步函数用的是哪一个锁呢?
函数需要被对象调用。那么函数都有一个所属对象引用。就是this。
所以同步函数使用的锁是this。
通过该程序进行验证。
使用两个线程来买票。
一个线程在同步代码块中。 这两个的锁不一样
一个线程在同步函数中。
都在执行买票动作。
*/ class Ticket implements Runnable { private int tick = 100; Object obj = new Object(); boolean flag = true; public void run() { if(flag) { while(true) { synchronized(this) /*同步函数的锁*/ { if(tick>0) { try{Thread.sleep(10);}catch(Exception e){} System.out.println(Thread.currentThread().getName()+"....code : "+ tick--); } } } } else while(true) show(); /*使用this锁*/ } public synchronized void show()//this { if(tick>0) { try{Thread.sleep(10);}catch(Exception e){} System.out.println(Thread.currentThread().getName()+"....show.... : "+ tick--); } } } class ThisLockDemo { public static void main(String[] args) { Ticket t = new Ticket(); Thread t1 = new Thread(t); Thread t2 = new Thread(t); t1.start(); try{Thread.sleep(10);}catch(Exception e){} t.flag = false; t2.start(); // Thread t3 = new Thread(t); // Thread t4 = new Thread(t); // t3.start(); // t4.start(); } }
二、多线程-静态同步函数的锁是class对象
/*
如果同步函数被静态修饰后,使用的锁是什么呢?
通过验证,发现不在是this。因为静态方法中也不可以定义this。
静态进内存是,内存中没有本类对象,但是一定有该类对应的字节码文件对象。
类名.class 该对象的类型是Class
静态的同步方法,使用的锁是该方法所在类的字节码文件对象。 类名.class
*/ class Ticket implements Runnable { private static int tick = 100; //Object obj = new Object(); boolean flag = true; public void run() { if(flag) { while(true) { synchronized(Ticket.class) /*使用了静态,锁就变了*/ { if(tick>0) { try{Thread.sleep(10);}catch(Exception e){} System.out.println(Thread.currentThread().getName()+"....code : "+ tick--); } } } } else while(true) show(); } public static synchronized void show() { if(tick>0) { try{Thread.sleep(10);}catch(Exception e){} System.out.println(Thread.currentThread().getName()+"....show.... : "+ tick--); } } } class StaticMethodDemo { public static void main(String[] args) { Ticket t = new Ticket(); Thread t1 = new Thread(t); Thread t2 = new Thread(t); t1.start(); try{Thread.sleep(10);}catch(Exception e){} t.flag = false; t2.start(); } }
三、多线程-单例设计模式-懒汉式 出现的安全问题
/*
单例设计模式。 必须要记住,面试题
饿汉式与懒汉式的区别
1.懒汉式是延时加载的形式
2.懒汉式由于是延时加载,所以在多线程中会出现安全问题
3.可以加同步函数或者同步代码块来解决,而同步函数每次都需要判断比较慢
4.这里采用同步代码块来解决安全问题
5.由于函数是静态的,所以锁是类名.class
*/ //饿汉式。 /* class Single { private static final Single s = new Single(); private Single(){} public static Single getInstance() { return s; } } */ //懒汉式 class Single { private static Single s = null; private Single(){} public static Single getInstance() { if(s==null) { synchronized(Single.class) { if(s==null) //--->A; s = new Single(); } } return s; } } class SingleDemo { public static void main(String[] args) { System.out.println("Hello World!"); } }
四、死锁(要避免出现和熟悉)
class Test implements Runnable { private boolean flag; Test(boolean flag) { this.flag = flag; } public void run() { if(flag) { while(true) { synchronized(MyLock.locka) { System.out.println(Thread.currentThread().getName()+"...if locka "); synchronized(MyLock.lockb) { System.out.println(Thread.currentThread().getName()+"..if lockb"); } } } } else { while(true) { synchronized(MyLock.lockb) { System.out.println(Thread.currentThread().getName()+"..else lockb"); synchronized(MyLock.locka) { System.out.println(Thread.currentThread().getName()+".....else locka"); } } } } } } class MyLock { static Object locka = new Object(); /*静态,能用类名直接调用*/ static Object lockb = new Object(); } class DeadLockTest { public static void main(String[] args) { Thread t1 = new Thread(new Test(true)); Thread t2 = new Thread(new Test(false)); t1.start(); t2.start(); } }