看了一些关于锁的文章,记录一下自己对锁的理解:
锁是对象锁用来保障代码的执行顺序锁是一个公共资源,被锁控制的线程都能访问到,但拿锁的过程尽量要快,因为它涉及到高并发锁的种类有很多,要是不会用的话最好用基础的Synchronized首先,第一个理解就是【锁】它是一个对象,任何一个Object对象都可以作为一个锁。Object中的notify、notifyAll、wait方法都是锁的方法。
notify是通知 一个 正在wait的线程,脱离wait状态,准备竞争锁。notifyAll是通知 所有 正在wait的线程,脱离wait状态,准备竞争锁。wait是释放锁,并进入wait状态,不被notify则不继续执行。而释放锁是在wait方法执行后或者是同步代码块执行完成后才会释放的,所以用的时候要考虑清楚再用。
之前理解的是notify后代码会继续执行,但写了一个小demo试了一下,发现不是的,notify之后其他同步代码块也不会执行,而是等待拿锁,同一时间,只有一个拿到锁(monitor)的同步块能够执行。
下面是一个小例子:
public class LockRunnable implements Runnable { public static void main(String[] args){ new Thread(new LockRunnable()).start(); LockRunnable.firstSay(); } public void run() { secondSay(); } public static synchronized void firstSay(){ try{ say("first1111"); Thread.sleep(1000); LockRunnable.class.wait(); say("first2222"); Thread.sleep(1000); say("first3333"); }catch (Exception e){ } } public static synchronized void secondSay(){ try{ say("second1111"); Thread.sleep(300); //notifyAll后会通知线程结束wait,进入准备竞争锁的状态。 LockRunnable.class.notifyAll(); say("second2222"); Thread.sleep(3000); say("second3333"); }catch (Exception e){ } } public static void say(String s){ System.out.println(s); } }输出:
first1111 second1111 second2222 second3333 first2222 first3333这里面有几个关键点:
static synchronized 锁的对象时 LockRunnable.class 这个对象,是类对象,这点从LockRunnable.class.notifyAll() 这里可以看出来,调用了LockRunnable.class的通知,却可以通知到被static synchronized锁住的secondSay方法。不拿到锁的话,即使被notify了,也不会继续往下执行代码。这点可以从输出结果看出,second3333 输出之前有3秒的sleep,若firstSay方法继续执行了,则会先打印出first2222才对。我们都知道,多线程的时候各个线程的执行和对临界资源的访问和单线程时不一样,需要考虑临界资源的线程安全问题,这时候就需要用到锁。
今天先写到这里,写的不对的欢迎大家批评指正哈~