java 大道至简--多线程(9)

                                       java 大道至简--多线程(9)

内容目录:

锁    

正文

前面的文章我们了解了线程的通信,线程的并发问题,可能大家注意到了一个问题,就是我们基本上都是用到了一个关键字,synchronized 其实在第一篇的博文中我们已经做了个最简单的了解,所以在这里对于锁的定义我就不做过多的解释了,本章我们就锁的应用做进一步的探讨和较为深入的研究

我门从以下三个方面进行探讨:

1、什么情况使用锁

2、怎么用

    2.1 synchronized关键字

    2.2 Lock接口

3、锁的常见问题和解决方案


1、什么情况使用锁

   通过多线程之间的通信,并发编程我们已经大致了解了我们什么时候要采用锁,总结就是一句话,在使用多线程的时候我们就要用到锁,你多线程用的好不好更多的还是看你对于锁的理解和使用到不到位

2、怎样使用锁

  在使用多线程的时候我们肯定会使用到锁,那么具体怎么来使用锁呢,我们再来简单的提一句锁的作用,就是为了满足内存一致性,我们将要操作的对象进行特殊处理,以此来告诉虚拟机,这个对象是同步的,即要检查内存一致,同时保护这个对象,防止其他线程对其操作,直到当前线程操作结束后,才能再次修改,那么这个特殊处理就是我们的锁,最常见也最方便的就是我们的关键字 sychronized,还有java.util.concurrent.Locks接口

3、锁的常见问题和解决方案

    死锁--多个线程彼此等待对方结束而被永久阻塞的情况

参看以下例子

    

package com.hello.test;


public class HelloWorld{


static Object lock1 = "a";

static Object lock2 = "b";

public static void main(String[] args) {

ThreadDemo1 thread1 = new ThreadDemo1();

ThreadDemo2 thread2 = new ThreadDemo2();

Thread thread3 = new Thread(thread1);

Thread thread4 = new Thread(thread2);

thread3.start();

thread4.start();

}

private static class ThreadDemo1 implements Runnable{


@Override

public void run() {

synchronized(lock1) {

System.out.println("Thread 1: Holding lock 1...");

try {

Thread.sleep(5*1000);

} catch (InterruptedException e) {

e.printStackTrace();

}

System.out.println("Thread 1: Holding lock 1...");

synchronized(lock2) {

System.out.println("Thread 1: Holding lock 1 & 2");

}

}

}

}


private static class ThreadDemo2 implements Runnable{


@Override

public void run() {

synchronized(lock2) {

System.out.println("Thread 2: Holding lock 2...");

try {

Thread.sleep(5*1000);

} catch (InterruptedException e) {

e.printStackTrace();

}

System.out.println("Thread 2: Holding lock 1...");

synchronized(lock1) {

System.out.println("Thread 2: Holding lock 1 & 2");

}

}

}

}

}

结果:

Thread 1: Holding lock 1...

Thread 2: Holding lock 2...

Thread 1: Holding lock 1...

Thread 2: Holding lock 1...

此时程序还在运行但是后面的

       System.out.println("Thread 1: Holding lock 1 & 2");

     System.out.println("Thread 2: Holding lock 1 & 2");

并没有执行,程序“卡住”了,

我们现在来分析一下为什么会“卡住”。

1、程序启动的时候我们同时启动了 ThreadDemo1 和ThreadDemo2 两个线程,并且会同时执行run()函数

2、synchronized的用法

   synchronized在java语言中是一个关键字,意思是同步,它可以用来修饰函数(方法),表示整个函数都是同步的,也可以在函数中单独使用,格式为:

   synchronized(Object){函数体} ,此结构通常称为同步代码块,类似静态代码块,表示当前线程获的对象(object)时,执行具体的函数体,synchronized会自动释放资源(锁),以供其他线程调用

3、ThreadDemo1首先获取lock1,ThreadDemo2首先获取lock2

4、ThreadDemo1执行第二个synchronized时试图获取lock2,但此时lock2已经被ThreadDemo2获取了,ThreadDemo1只好等待lock2被释放

5、ThreadDemo2执行第二个synchronized时试图获取lock1,但此时lock1已经被ThreadDemo1获取了,ThreadDemo2只好等待lock1被释放

6、就这样两个线程相互等待对方释放资源,就像拔河比赛,我等你先放手,你等我先放手,就这样相互纠缠直到永远

以上是分析造成死锁的原因,因为篇幅有限,所以下一篇我们来介绍如何解决这个死锁问题,

  



猜你喜欢

转载自blog.csdn.net/xianghan_qq/article/details/80703736