七、多线程(未完.待更)

序言

指从软件或者硬件上实现多个线程并发执行的技术。具有多线程能力的计算机因有硬件支持而能够在同一时间执行多于一个执行绪,进而提升整体处理性能

Java多线程两种方式:

  • 继承Thread
  • 实现Runnable

synchronized的两种种用法

锁对象.当所有的线程都访问这个对象的同一个方法.锁

public void test(){
     synchronized(this){ 
     }
}

//等价
public synchronized void test(){
}

锁类型.所有的线程访问当前class.锁

//demo中锁的是A这种类型
public void test(){
     synchronized(A.class){ 
     }
}
//等价
public static synchronized test(){
}

synchronized释放锁的三种情况:

1)获取锁的线程执行完了该代码块,然后线程释放对锁的占有;

2)线程执行发生异常,此时JVM会让线程自动释放锁。

3)这个主要是在等待唤醒机制里面的wait()方法,//在等待的时候立即释放锁,方便其他的线程使用锁。而且被唤醒时,就在此处唤醒,

synchronized死锁的情况

1.创建两把锁对象

public class MyLock {
    
    
    // 创建两把锁对象
     public static final Object objA = new Object();
     public static final Object objB = new Object();
 }

2.死锁程序

public class DieLock extends Thread {
    
    

    private boolean flag;

    public DieLock(boolean flag) {
        this.flag = flag;
    }

    @Override
    public void run() {
        if (flag) {
            synchronized (MyLock.objA) {
                System.out.println("if objA");
                synchronized (MyLock.objB) {
                    System.out.println("if objB");
                }
            }
        } else {
            synchronized (MyLock.objB) {
                System.out.println("else objB");
                synchronized (MyLock.objA) {
                    System.out.println("else objA");
                }
            }
        }
    }
}

3.死锁测试demo

/*
 * 同步的弊端:
 *         A:效率低
 *         B:容易产生死锁
 * 
 * 死锁:
 *         两个或两个以上的线程在争夺资源的过程中,发生的一种相互等待的现象。
 * 
 * 举例:
 *         小明和小强的自行车都有两把锁一人一把钥匙案例。
 *         正常情况:
 *             小明: 两把锁的钥匙都有;
 *             小强: 两把锁的钥匙都有。
 *         现在:
 *             小明:有其中一把锁的两把钥匙;
 *             小强:有另一把锁的两把钥匙。
 *             结局两个人都不能打开锁。。。。一直等待朔夜起不到自行车
 */
public class DieLockDemo {
    public static void main(String[] args) {
        DieLock dl1 = new DieLock(true);
        DieLock dl2 = new DieLock(false);

        dl1.start();
        dl2.start();
    }
}

4.运行结果

if objA
else objB

5.结果说明
我们知道synchronized里面的代码执行完才释放锁.当dl1进入if的synchronized (MyLock.objA) .同时dl2也进入else的synchronized (MyLock.objB) .这个时候就会有如下情况

  • 想要执行完synchronized (MyLock.objA) {….}里面的逻辑,必须先要拿到synchronized (MyLock.objB) 的锁,但是此时已经被dl2也进入else的synchronized (MyLock.objB)锁住了,无法拿到.synchronized (MyLock.objA) {….}里面的逻辑无法执行完
  • dl2进入else的synchronized (MyLock.objB).因为synchronized (MyLock.objA) {….}无法执行完,没办法释放MyLock.objA的锁.导致synchronized (MyLock.objB){…}的逻辑也无法执行完

关于synchronized的详细说明.写的非常好
http://blog.csdn.net/xiao__gui/article/details/8188833

关于死锁的逻辑.写的特别清晰
http://www.cnblogs.com/fuck1/p/5432806.html

lock操作

Lock操作是对synchronized的局限性进行了一些补充(虽然比较长….但是老哥我写的比较好懂):

  • 局限性说明:一个对象假设有三个非static的synchronized方法(method1,method2,method3).你有一个线程去访问method1,此时你又开启一个新线程去访问method2.如果method1没有释放释放synchronized的锁.你就进不去method2.如果method1是读的操作.method2也是读的操作.并不会影响原子性操作.但是你硬生生全给synchronized
  • lock的解决方式:那你会说,既然没有原子操作.我就不加synchronized,老哥你别给我整这些没用的道道,好吧,如果method3是写操作.要和method1结合,这个时候就有必要了.因为读写锁会互斥.你的读锁就可以和写锁发挥功效了,如果是synchronized,虽然也是读写操作互斥,读和读的情况就会降低多线程的访问效率

上面只是一种情况.接下来我给大家说说Lock的常用操作(先占个位置.回来再补充)

线程间通信(先占个位置)

猜你喜欢

转载自blog.csdn.net/aa375809600/article/details/72689678