java多线程_复习宝典02

线程安全

多线程条件下保证线程安全 采用加锁机制

Synchronized

1)可以在任意对象以及方法上加锁 倍加锁的代码成为 互斥区 或 临界区
2)多线程条件下 排队按照CPU分的方式进入同步队列 一个线程执行sunchronize其他线程拿不到 就会出现锁竞争
3)
* 对于普通同步方法,锁是当前实例对象
* 对于静态同步方法,锁是当前类的Class对象
* 对于同步方法块,锁是Synchronized括号里配置的对象

Sychronize实现原理

1)内置锁和护斥锁
内置锁 每一个继承Object的对象都可以用实现同的锁 线程进入同步代码块同步方法都会获得 该所 退出时释放
互斥锁 内置锁通过互斥所实现 某一个时刻最多只能有一个线程持该锁

#1)实现原理

1.每一个对象都会有一个monitor
2. 当一个线程获取一个对象 通过monitor监视器就会获取对象的monitor
3.当这个对象被加锁 线程monitor监视器计数器count++
4.其他对象因为监视器count不为0 无法进入锁的代码块
5.当这个对象执行完毕 锁的代码块 monitor监视器计数器count–
6.当count=0时其他对象都有可能会被获取
7.调用wait()方法是 释放当前持有的monitor

2)sychronized锁可重入

在一个被sychronized修饰的代码块中再次添加对象锁sychronized双重加锁如果锁的是同一个对象 就会成功不受阻塞
实现对多个对象加锁 static修饰
出现异常锁自动释放

3)应用单例模式(普通加锁)
class Singleton{
    private static Singleton instance = null;
    private Singleton(){

    }
    public static synchronized Singleton newinstance(){
        if(instance == null){
            instance = new Singleton();
        }
        return instance;
    }
}

保证同一时刻只能有一个线程进入 产生一个对象 线程安全

4)单例模式(双重校验锁)
class DubbleSingleton{
    //private static DubbleSingleton instance;
    private static volatile  DubbleSingleton instance;

    public static DubbleSingleton getinstance(){
        if(instance==null){
            synchronized (DubbleSingleton.class){
                if(instance==null){
                    instance = new DubbleSingleton();
                }
            }
        }
        return instance;
    }
}

采用双重判断加锁的模式 避免多个线程同时进入创建对象
减小锁粒度 锁优化的一种
但是因为JVM虚拟机 会重新编译文件存在 指令重排优化 可能导致初始化丹迪对象将该对象的地址复制给instance字段顺序与上面java中顺序不同
使用volatile 修饰 进制指令重排序优化
Sychronize锁优化(JDK 1.6之后)

5)锁的四种状态 无所状态—>偏向锁状态—>轻量级锁—>重量级锁

偏向锁 : 乐观锁如果一个线程获取到了锁 那么锁进入偏向模式 当这个锁再次请求锁时 无需在进行任何操作
轻量级锁 : 当一个线程访问同步资源 锁竞争不激烈 很有可能对此请求来自同一个线程 偏向锁失败 升级成轻量级锁 实质将对象mark-word头部致真 指向线程堆栈 内部 判断是否持有对象
重量级锁: 轻量级锁失败 膨胀成重量级锁
自旋锁 : 轻量级锁失败后 JVM会进行 自旋锁 让当前线程做空循环 获取则成功不获取 则挂起

(1)CAS自旋锁

需要读写的内存值 V 进行比较的值 A 拟写入的新值 B
当V==A 时 CAS 通过原子方式 使用B 更新V值
锁粗化
连续的多个srchronize修饰的代码块 且 加锁的对象 是同一个则我们可以将这些代码块合并 采用一个srchroinzed加锁 但是要连续

public class test {
    public void coarse(){
        synchronized (test.class){
            //TDDD
        }
        synchronized (test.class){
            //TDDD2
        }
    }

合并后

public class test {
    public void coarse(){
       synchronized (test.class){
           //TDDD
           //TDDD2
       }
    }

减小开销提高效率

(2)锁消除

Jvm 在编译器运行时检测到没必要加锁的内容会自动去除

线程间通信

Object类下
Wait() 等待将正在执行的线程书房器质性资格和执行权 不出存在线程池中
notify() 唤醒 唤醒 唤醒鲜橙汁中被wait() 调用的线程 随机唤醒
NotifyAll() 唤醒全部wait()等待线程

package main.ProducerAndConsumer;
class Resource{
    private String name;
    private int count = 1;
    private boolean flag;

    public synchronized void set(String name){
        while(flag){
            try{
                this.wait();
            }catch (Exception e){
                e.printStackTrace();
            }
        }
        this.name = name + count;

        count++;

        System.out.println(
                Thread.currentThread().getName()+"This was producered" +
                        ":"+this.name);
        flag = true;
        this.notifyAll();
    }
    public synchronized void out(){
        while(!flag){
            try{
                this.wait();
            }catch (Exception e){
                e.printStackTrace();
            }
        }
        count--;
        System.out.println(Thread.currentThread().getName()
        +"The consumer is:"+this.name);

        flag = false;
        this.notifyAll();
    }
}
class Producer implements Runnable{
    private Resource r;
    public Producer(Resource r){
        this.r = r;
    }
    @Override
    public void run() {
        while(true){
            r.set("商品");
        }
    }
}
class Consumer implements Runnable{
    private Resource r;
    public Consumer(Resource r){
        this.r = r;
    }
    @Override
    public void run() {
        while (true){
            r.out();
        }
    }
}

public class ProAndCons {
    public static void main(String[] args) {
        Resource r = new Resource();
        Producer pro = new Producer(r);
        Consumer con = new Consumer(r);
        Thread t1 = new Thread(pro);
        Thread t2 = new Thread(pro);
        Thread t3 = new Thread(con);
        Thread t4 = new Thread(con);

        t1.start();
        t2.start();
        t3.start();
        t4.start();
    }
}

两个线程间的协同操作 使用while保证每一次线程被唤醒之后都需要进行判断,不会发生两个线程同时进行wait()发生死锁问题

死锁

产生死锁的条件
(1)至少一个资源不共享
(2)至少一个任务持有一个资源并且等待获取另一个被别的任务持有的资源
(3)资源不能任务抢占
(4)必须循环等待
只需要破坏其中一个就不会产生死锁
1.两个线程发生交叉闭环 线程A 获得锁A需要锁B 才能释放A ,线程B 获得锁B的情况下才能释放A,等待对方释放资源自己才能结束陷入死锁

package main;
class DeadLockA implements Runnable{
    @Override
    public void run() {
        try{
            System.out.println("锁A开启");
        }catch (Exception e){
            while(true){
                synchronized (DeadLock.obj1){
                    System.out.println("进入锁A:获取锁B释放B");
                    synchronized (DeadLock.obj2){
                        System.out.println("进入锁A的锁B区成功");
                    }
                }
            }
        }
    }
}
class DeadLockB implements Runnable{
    @Override
    public void run() {
        try{
            System.out.println("锁B开启");
        }catch (Exception e){
            while(true){
                synchronized (DeadLock.obj2){
                    System.out.println("进入锁B:获取锁A释放A");
                    synchronized (DeadLock.obj1){
                        System.out.println("进入锁B的锁A区成功");
                    }
                }
            }
        }
    }
}
public class DeadLock {
    public static final String obj1 = "锁A";
    public static final String obj2 = "锁B";

    public static void main(String[] args) {
        DeadLockA a = new DeadLockA();
        DeadLockB b = new DeadLockB();
        Thread t1 = new Thread(a);
        Thread t2 = new Thread(b);
        t1.start();
        t2.start();
    }
}

结果

线程A 等待线程B 线程B等待线程A 发生死锁问题

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值