首页 > 编程语言 >java并发编程(二十二)-并发安全的基本概念

java并发编程(二十二)-并发安全的基本概念

时间:2022-11-30 14:41:40浏览次数:41  
标签:java 变量 int age 编程 list 并发 线程 public


类的线程安全定义  

如果多线程下使用这个类,不过多线程如何使用和调度这个类,这个类总是表示出正确的行为,这个类就是线程安全的。

类的线程安全表现为:

  1. 操作的原子性
  2. 内存的可见性

不做正确的同步,在多个线程之间共享状态的时候,就会出现线程不安全。

怎么才能做到类的线程安全?

栈封闭

所有的变量都是在方法内部声明的,这些变量都处于栈封闭状态。

无状态

没有任何成员变量的类,就叫无状态的类

package com.caojiulu;

/**
*
*@author caojiulu
*
*类说明:无状态的类,没有任何的成员变量
*/
public class StatelessClass {

public int service(int a,int b) {
return a*b;
}


}

让类不可变

让状态不可变,两种方式:

1,加final关键字,对于一个类,所有的成员变量应该是私有的,同样的只要有可能,所有的成员变量应该加上final关键字,但是加上final,要注意如果成员变量又是一个对象时,这个对象所对应的类也要是不可变,才能保证整个类是不可变的。

示例代码:

package com.caojiulu;


/**
*@author caojiulu
*
*类说明:看起来不可变的类,实际是可变的
*/
public class ImmutableFinalRef {

private final int a;
private final int b;
private final User user;//这里,就不能保证线程安全啦

public ImmutableFinalRef(int a, int b) {
super();
this.a = a;
this.b = b;
this.user = new User(2);
}

public int getA() {
return a;
}

public int getB() {
return b;
}

public User getUser() {
return user;
}

public static class User{
private int age;

public User(int age) {
super();
this.age = age;
}

public int getAge() {
return age;
}

public void setAge(int age) {
this.age = age;
}

}

public static void main(String[] args) {
ImmutableFinalRef ref = new ImmutableFinalRef(12,23);
User u = ref.getUser();
u.setAge(35);
}
}

2、根本就不提供任何可供修改成员变量的地方,同时成员变量也不作为方法的返回值

volatile

保证类的可见性,最适合一个线程写,多个线程读的情景,

加锁和CAS

 

安全的发布

类中持有的成员变量,特别是对象的引用,如果这个成员对象不是线程安全的,通过get等方法发布出去,会造成这个成员对象本身持有的数据在多线程下不正确的修改,从而造成整个类线程不安全的问题。

package com.caojiulu;

import java.util.ArrayList;
import java.util.List;

/**
*@author caojiulu
*
*类说明:存在着不安全的发布
*/
public class UnsafePublish {
//要么用线程的容器替换
//要么发布出去的时候,提供副本,深度拷贝
private List<Integer> list = new ArrayList<>(3);

public UnsafePublish() {
list.add(1);
list.add(2);
list.add(3);
}

//讲list不安全的发布出去了
public List<Integer> getList() {
return list;
}

//也是安全的,加了锁--------------------------------
public synchronized int getList(int index) {
return list.get(index);
}

public synchronized void set(int index,int val) {
list.set(index,val);
}

}

TheadLocal

ThreadLocal的实例代表了一个线程局部的变量,每条线程都只能看到自己的值,并不会意识到其它的线程中也存在该变量。

它采用采用空间来换取时间的方式,解决多线程中相同变量的访问冲突问题。

 

标签:java,变量,int,age,编程,list,并发,线程,public
From: https://blog.51cto.com/u_14906615/5899411

相关文章

  • java并发编程(二十三)-并发安全之死锁
    死锁资源一定是多于1个,同时小于等于竞争的线程数,资源只有一个,只会产生激烈的竞争。死锁的根本成因:获取锁的顺序不一致导致。 死锁的一般情况:packagecom.caojiulu;importc......
  • java并发编程(一)-线程相关的基本概念
    CPU核心数和线程数的关系核心数:线程数=1:1intel引入超线程技术之后--》核心数:线程数=1:2CPU时间片轮转机制-又称RR调度 时间片轮转法(Round-Robin,RR)主要用于分时系统......
  • java并发编程(三)-线程的协作式
    怎么样才能让Java里的线程安全停止工作呢?一般来说:程序执行完或者抛出异常。怎么用代码的方式将线程停止呢?可以看到stop(),resume(),suspend()已不建议使用,stop()会导致线程......
  • 【JAVA基础】SQL示例
    SQL示例insert操作<!--id属性:表示映射的接口中方法的名称,直接标签的内容部来编写SQL语句--><!--useGeneratedKeys="true"表示开启某个字段的值递增(大部分都是......
  • Java 集合框架1:Collection
    目录集合框架1.概述2.Collection基本方法容器遍历容器实现元素排序3.Collections包装器实现(WrapperImplementations)Empty对象不可变单例Set(ImmutableSingletonSet)不可......
  • java 环境变量配置详细教程(2023 年全网最详细)
    前言:在上一篇文章中,壹哥给大家重点讲解了Java实现跨平台的原理,不知道你现在有没有弄清楚呢?如果你还有疑问,可以在评论区留言~之前的三篇文章,主要是理论性的内容,其实你暂......
  • Promise手动实现和Async Await拓展(JavaScript)
    Promise手动实现咱们来看一段Promise的代码:letp1=newPromise((resolve,reject)=>{resolve('成功')reject('失败')![]()})console.log('p1',p1)le......
  • java排序算法
     一.冒泡排序特点:实现简单,无额外空间消耗,速度较慢,适合数据较少的场景,复杂度为O(N^2)思路:每一轮比较都从头开始,然后两两比较,如果左值比右值大,则交换位置,每一......
  • 实验四 Web服务器1-socket编程
    实验要求:基于华为鲲鹏云服务器CentOS中(或Ubuntu),使用LinuxSocket实现:time服务器的客户端服务器,提交程序运行截图echo服务器的客户端服务器,提交程序运行截图,服务器把......
  • 高并发系统之限流特技
    在开发高并发系统时有三把利器用来保护系统:缓存、降级和限流。缓存的目的是提升系统访问速度和增大系统能处理的容量,可谓是抗高并发流量的银弹;而降级是当服务出问题或者影响......