首页 > 试题广场 >

如何保证线程安全?

[问答题]
1、使用线程安全的类; 2、使用synchronized同步代码块,或者用Lock锁; > 由于线程安全问题,使用synchronized同步代码块 原理:当两个并发线程访问同一个对象object中的这个synchronized(this)同步代码块时,一个时间内只能有一个线程得到执行。 另一个线程必须等待当前线程执行完这个代码块以后才能执行该代码块。

3、多线程并发情况下,线程共享的变量改为方法局部级变量;

发表于 2019-04-25 18:45:19 回复(0)
同步方法同步代码块volatile,就知道这些
发表于 2019-03-12 20:00:24 回复(0)
我来补充四种:
1)synchronized关键字  
2)lock接口
3)volatile+CAS【单纯的volatile是轻量级的同步机制保证可见性但是不具备原子性所以要配合CAS来实现线程安全】
4)atomic原子类【比较冷门,大家可以去看看】
发表于 2019-04-04 14:05:57 回复(0)
😃
发表于 2020-03-23 16:53:51 回复(0)
考察点:线程 参考回答: 通过合理的时间调度,避开共享资源的存取冲突。另外,在并行任务设计上可以通过适当的策略,保证任务与任务之间不存在共享资源,设计一个规则来保证一个客户的计算工作和数据访问只会被一个线程或一台工作机完成,而不是把一个客户的计算工作分配给多个线程去完成。
发表于 2019-05-01 21:41:02 回复(0)
线程安全 
一般说来,确保线程安全的方法有这几个:竞争与原子操作、同步与锁、可重入、过度优化。

竞争与原子操作 
多个线程同时访问和修改一个数据,可能造成很严重的后果。出现严重后果的原因是很多操作***作系统编译为汇编代码之后不止一条指令,因此在执行的时候可能执行了一半就被调度系统打断了而去执行别的代码了。一般将单指令的操作称为原子的(Atomic),因为不管怎样,单条指令的执行是不会被打断的。

因此,为了避免出现多线程操作数据的出现异常,Linux系统提供了一些常用操作的原子指令,确保了线程的安全。但是,它们只适用于比较简单的场合,在复杂的情况下就要选用其他的方法了。

同步与锁 
为了避免多个线程同时读写一个数据而产生不可预料的后果,开发人员要将各个线程对同一个数据的访问同步,也就是说,在一个线程访问数据未结束的时候,其他线程不得对同一个数据进行访问。

同步的最常用的方法是使用锁(Lock),它是一种非强制机制,每个线程在访问数据或资源之前首先试图获取锁,并在访问结束之后释放锁;在锁已经被占用的时候试图获取锁时,线程会等待,直到锁重新可用。

二元信号量是最简单的一种锁,它只有两种状态:占用与非占用,它适合只能被唯一一个线程独占访问的资源。对于允许多个线程并发访问的资源,要使用多元信号量(简称信号量)。

可重入 
一个函数被重入,表示这个函数没有执行完成,但由于外部因素或内部因素,又一次进入该函数执行。一个函数称为可重入的,表明该函数被重入之后不会产生任何不良后果。可重入是并发安全的强力保障,一个可重入的函数可以在多线程环境下放心使用。

过度优化 
在很多情况下,即使我们合理地使用了锁,也不一定能够保证线程安全,因此,我们可能对代码进行过度的优化以确保线程安全。

我们可以使用volatile关键字试图阻止过度优化,它可以做两件事:第一,阻止编译器为了提高速度将一个变量缓存到寄存器而不写回;第二,阻止编译器调整操作volatile变量的指令顺序。

在另一种情况下,CPU的乱序执行让多线程安全保障的努力变得很困难,通常的解决办法是调用CPU提供的一条常被称作barrier的指令,它会阻止CPU将该指令之前的指令交换到barrier之后,反之亦然。

发表于 2019-04-25 23:06:17 回复(0)
1)synchronized关键字  
2)lock接口
3)volatile+CAS
发表于 2019-04-25 20:38:22 回复(0)