java线程解决同步问题的5种方法

参考:

https://www.cnblogs.com/goody9807/p/6522176.html

背景:

线程创建的两种方法:
1. 继承runnable接口传入Thread
实例对象作为单实例传递给Thread 所以创建多个线程共用一个实例对象,里面的属性也都是共享的。
2. 继承Thread
多线程工作原理:
线程1:操作步骤–工作内存–总内存。
线程2:操作步骤–工作内存–总内存。
线程3:操作步骤–工作内存–总内存。
流程:
每个线程从总内存种读取内存到工作内存,然后在操作步骤中对共享数据进行操作,将修改后的数据更新到工作内存,再更新到总内存。


方法一:validate :针对工作内存–总内存

修饰共享变量,保持数据可见性,适用范围:只读取,不修改。
意思:当多线程访问共享数据的时候只是读取,没有修改,这个时候就可以使用validate。

只需在共享数据前面加上volatile修饰,即可实现线程同步。


方法二,三:synchronized同步方法和同步块

这两种方式都要用到synchronized关键字。
synchronized锁住代码块,保持顺序性。
意思就是 使得线程内是顺序执行,线程间是随机。
流程:
每个对象都有一个“锁标志”,当这个对象的一个线程访问这个对象的某个synchronized 数据时,这个对象的所有被synchronized 修饰的数据将被上锁(因为“锁标志”被当前线程拿走了),
只有当前线程访问完它要访问的synchronized 数据时,当前线程才会释放“锁标志”,这样同一个对象的其它线程才有机会访问synchronized 数据。

synchronized 关键字用于保护共享数据 目的是使同一个对象的多个线程,在某个时刻只有其中的一个线程可以访问这个对象的synchronized 数据。
所以尽量只给操作共享数据的代码块加synchronized锁一般使用同步块,锁的内容少,开销小。


方法四:重入锁ReentrantLock

链接:重入锁:ReentrantLock 详解
链接:线程调度之ReentrantLock实现 多线程顺序执行任务

ReentrantLock() : 创建一个ReentrantLock实例
ReentrantLock()还有一个可以创建公平锁的构造方法,但由于能大幅度降低程序运行效率,不推荐使用

lock() : 获得锁 
unlock() : 释放锁 

注:关于Lock对象和synchronized关键字的选择:
a.最好两个都不用,使用一种java.util.concurrent包提供的机制,能够帮助用户处理所有与锁相关的代码。
b.如果synchronized关键字能满足用户的需求,就用synchronized,因为它能简化代码
c.如果需要更高级的功能,就用ReentrantLock类,此时要注意及时释放锁,否则会出现死锁,通常在finally代码释放锁

public static ReentrantLock lock = new ReentrantLock();
  @Override
    public void run() {
        for (int j = 0; j < 10000; j++) {
            lock.lock();  // 看这里就可以
            //lock.lock(); ①
            try {
                i++;
            } finally {
                lock.unlock(); // 看这里就可以
                //lock.unlock();②
            }
        }
    }

注意:需要手动来释放重入锁


方法五:局部变量实现线程同步(非阻塞型)

使用局部变量实现线程同步:采用以”空间换时间”的方法,与前面方法采用的”时间换空间”不同
ThreadLocal:
注:ThreadLocal与同步机制
a.ThreadLocal与同步机制都是为了解决多线程中相同变量的访问冲突问题。

题外话:线程的释放锁重点内容
wait():使一个线程处于等待状态,并且释放所持有的对象的lock。

sleep():使一个正在运行的线程处于睡眠状态,是一个静态方法,调用此方法要捕捉InterruptedException异常。
notify():唤醒一个处于等待状态的线程,注意的是在调用此方法的时候,并不能确切的唤醒某一个等待状态的线程,而是由JVM确定唤醒哪个线程,而且不是按优先级。

  • 0
    点赞
  • 11
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值