关于保障线程安全的几种方法

原文:https://www.cnblogs.com/lixinjie/p/10817860.html

原文:关于保障线程安全的几种方法,通俗易懂 - doraemonlin - 博客园 https://www.cnblogs.com/yuanmaolin/p/11090380.html

我从文中学到的几点(线程安全方面):

在多线程环境中,存在于堆内存的公共资源可以被很多线程访问,也就存在安全隐患(数据容易被修改)。

所以,为了保障数据的安全,就要对这些数据做些处理。

一、从变量上着手:

方法一:将变量放在方法中,也就是局部变量【操作系统会为每个线程分配属于它自己的内存空间,通常称为栈内存,其它线程无权访问,而局部变量在栈内存中】

复制代码

double avgScore(double[] scores) {
double sum = 0;
for (double score : scores) {
sum += score;
}
int count = scores.length;
double avg = sum / count;
return avg;
}

复制代码
方法二:变量在类中的方法外 ,即成员变量,这时可以利用ThreadLocal【原理:多个线程访问同一共享变量时,ThreadLocal类为每个线程提供一份该变量的副本,各个线程拥有一份属于自己的变量副本,操作修改的是各自的变量副本,而不会相互影响。】

复制代码

class StudentAssistant {

ThreadLocal<String> realName = new ThreadLocal<>();
ThreadLocal<Double> totalScore = new ThreadLocal<>();

String determineDegree() {
    double score = totalScore.get();
    if (score >= 90) {
        return "A";
    }
    if (score >= 80) {
        return "B";
    }
    if (score >= 70) {
        return "C";
    }
    if (score >= 60) {
        return "D";
    }
    return "E";
}

double determineOptionalcourseScore() {
    double score = totalScore.get();
    if (score >= 90) {
        return 10;
    }
    if (score >= 80) {
        return 20;
    }
    if (score >= 70) {
        return 30;
    }
    if (score >= 60) {
        return 40;
    }
    return 60;
}

}
复制代码
方法三:变量+final,即变成常量(只能读,不能修改)

class StudentAssistant {

final double passScore = 60;

}
二、从锁着手【公共区域(堆内存)的数据,要被多个线程操作时,为了确保数据的安全(或一致)性,需要在数据旁边放一把锁,要想操作数据,得先获取锁】

方法一:悲观锁【认定数据一定不安全,不管怎样,想访问数据就需要锁,没锁的访问不了】

复制代码

class ClassAssistant {

double totalScore = 60;
final Lock lock = new Lock();

void addScore(double score) {
    lock.obtain();    //获取锁
    totalScore += score;
    lock.release();   //释放锁
}

void subScore(double score) {
    lock.obtain();
    totalScore -= score;
    lock.release();
}

}

复制代码
方法二:乐观锁【在高并发时可以用悲观锁,但在低并发时,数据被意外修改的概率很低,(假如只有一个线程)再用悲观锁(获得锁、释放锁)可能就会造成浪费,这时可以用乐观锁即CAS】

乐观锁:假如一个线程操作数据,做到一半,休息了,就记录下数据的值,等回来继续做时,先将记录的数据与当前数据对比,如果一样就继续干,不一样就重新做。

乐观锁存在ABA问题,即数据有可能被变动过了,但后面又改了回来,这时数据值没变,但其实被动过了。

解决ABA问题:加一个版本号字段,数据若变动一次,版本号就加一,变动两次就加二。

  • 0
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

Ariel小葵

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值