线程安全以及死锁问题

死锁

死锁是指多个线程运行过程中因争夺资源而造成的一种僵局,当进程处于这种僵持状态时,若无外力作用,它们都将无法再向前推进。

产生死锁的四个必要条

  1. 互斥条件:进程要求对所分配的资源进行排它性控制,即在一段时间内某资源仅为一进程所占用。
  2. 请求和保持条件:当进程因请求资源而阻塞时,对已获得的资源保持不放。
  3. 不剥夺条件:进程已获得的资源在未使用完之前,不能剥夺,只能在使用完时由自己释放。
  4. 环路等待条件:在发生死锁时,必然存在一个进程--资源的环形链。

编写产生死锁的代码

复制代码
public class TestDeadLock {
    private static Object obj1 = new Object();
    private static Object obj2 = new Object();

    public static void main(String[] args) {
        new Thread(new Thread1()).start();
        new Thread(new Thread2()).start();
    }

    private static class Thread1 implements Runnable {
        @Override
        public void run() {
            synchronized (obj1) {
                System.out.println("Thread1 拿到了 obj1 的锁!");
                try {
                // 停顿2秒的意义在于,让Thread2线程拿到obj2的锁
                    Thread.sleep(2000);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
                synchronized (obj2) {
                    System.out.println("Thread1 拿到了 obj2 的锁!");
                }
            }
        }
    }

    private static class Thread2 implements Runnable {
        @Override
        public void run() {
            synchronized (obj2) {
                System.out.println("Thread2 拿到了 obj2 的锁!");
                try {
                // 停顿2秒的意义在于,让Thread1线程拿到obj1的锁
                    Thread.sleep(2000);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
                synchronized (obj1) {
                    System.out.println("Thread2 拿到了 obj1 的锁!");
                }
            }
        }
    }

}
复制代码

使用jstack加上进程号进行查看

预防死锁:

  1. 资源一次性分配:一次性分配所有资源,这样就不会再有请求了:(破坏请求条件)
  2. 只要有一个资源得不到分配,也不给这个进程分配其他的资源:(破坏请保持条件)
  3. 可剥夺资源:即当某进程获得了部分资源,但得不到其它资源,则释放已占有的资源(破坏不可剥夺条件)
  4. 资源有序分配法:系统给每类资源赋予一个编号,每一个进程按编号递增的顺序请求资源,释放则相反(破坏环路等待条件)

线程安全

模拟线程不安全代码

复制代码
public class Test {
    private static Integer count=0;
    public  static void add(){
        count++;
    }
   static CountDownLatch downLatch=new CountDownLatch(100);
    public static void main(String[] args) throws InterruptedException {

        for (int i = 0; i <100 ; i++) {

            new Thread(()->{
                for (int j = 0; j <10 ; j++) {
                    add();
                }
                downLatch.countDown();
            }).start();

        }
        downLatch.await();
        System.out.println(count);

    }
}
复制代码

解决方案

1:添加synchronized

复制代码
public class Test {
    private static Integer count=0;
    public synchronized  static void add(){
        count++;
    }
   static CountDownLatch downLatch=new CountDownLatch(100);
    public static void main(String[] args) throws InterruptedException {

        for (int i = 0; i <100 ; i++) {

            new Thread(()->{
                for (int j = 0; j <10 ; j++) {
                    add();
                }
                downLatch.countDown();
            }).start();

        }
        downLatch.await();
        System.out.println(count);

    }
}
复制代码

2.加lock锁

复制代码
import java.util.concurrent.CountDownLatch;
import java.util.concurrent.locks.ReentrantLock;

public class Test {
    private static Integer count = 0;

    public  static void add() {
        try {
            reentrantLock.lock();
            count++;
        } catch (Exception e) {
            e.printStackTrace();
        } finally {
            reentrantLock.unlock();
        }


    }

    static ReentrantLock reentrantLock = new ReentrantLock();
    static CountDownLatch downLatch = new CountDownLatch(100);

    public static void main(String[] args) throws InterruptedException {

        for (int i = 0; i < 100; i++) {

            new Thread(() -> {
                for (int j = 0; j < 10; j++) {
                    add();
                }
                downLatch.countDown();
            }).start();

        }
        downLatch.await();
        System.out.println(count);

    }
}
复制代码

3.上面的这种情况还可以使用原子类

复制代码
package test;

import java.util.concurrent.CountDownLatch;
import java.util.concurrent.atomic.AtomicInteger;

public class Test {
    private static AtomicInteger count = new AtomicInteger(0);

    public  static void add() {
        count.incrementAndGet();
    }

    static CountDownLatch downLatch = new CountDownLatch(100);

    public static void main(String[] args) throws InterruptedException {

        for (int i = 0; i < 100; i++) {

   
原文地址:https://www.cnblogs.com/wangdayexinyue/p/12521341.html