关闭

确保线程安全的几种方法

2280人阅读 评论(1) 收藏 举报
分类:

对于基于Linux操作系统的开发者来说,多线程是一个在开发和面试中不可避免的、被广泛讨论的话题。最近,我被问到了一个和多线程有关的问题:如何确保线程安全?在刚听到这个问题的时候,我还一时回答不上来。后面,我查找了与线程安全相关的资料,算是补上了问题的答案。本文首先对线程进行简单的介绍,然后介绍几种保证线程安全的方法。

线程简介
在介绍线程之前,要引入进程(Process)的概念。进程有狭义和广义之分,狭义的进程是正在运行的程序的实例;广义的进程是一个具有一定独立功能的程序关于某个数据集合的一次运行活动,是操作系统动态执行的基本单元。

线程(Thread),有时被称为轻量级进程(LWP),是程序执行流的最小单位;一个标准的线程由线程ID、当前指令指针(PC)、寄存器集合和堆栈组成。通常情况下,一个进程由一个到多个线程组成,各个线程之间共享程序的内存空间及一些进程级的资源。

在大多数软件应用中,线程的数量都不止一个,多线程程序处在一个多变的环境中,可访问的全局变量和堆数据随时都可能被其他的线程改变,这就将“线程安全”的问题提上了议程。那么,如何确保线程的安全呢?

线程安全
一般说来,确保线程安全的方法有这几个:竞争与原子操作、同步与锁、可重入、过度优化

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

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

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

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

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

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

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

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

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

1
0
查看评论
发表评论
* 以上用户言论只代表其个人观点,不代表CSDN网站的观点或立场

多线程中如何去保证线程安全

http://www.cnblogs.com/qingche/p/5695743.html 一、前言   前段时间看了几个开源项目,发现他们保持线程同步的方式各不相同,...
  • tianyitianyi1
  • tianyitianyi1
  • 2016-07-27 08:47
  • 4001

java线程安全总结

原文:    http://www.iteye.com/topic/806990 http://www.iteye.com/topic/808550          最近想将java基础的一...
  • haolongabc
  • haolongabc
  • 2012-02-10 16:22
  • 87381

如何保证单例模式在多线程中的线程安全性

如何保证单例模式在多线程中的线程安全性         对大数据、分布式、高并发学习必须要有多线程的基础。这里讨论一下如何在多线程的情况下设计单例模式。在23中设计模式中单例模式是比较常见的,在非多线...
  • u012100371
  • u012100371
  • 2017-05-05 13:56
  • 1076

线程安全的理解和如何保证线程安全

线程安全的理解和如何保证线程安全 http://www.cnblogs.com/mindsbook/archive/2009/10/15/thread-safety-and-GIL.html 线程...
  • gukesdo
  • gukesdo
  • 2012-05-15 15:39
  • 8409

如何做到java线程安全

[b]保证线程安全的三种方法:[/b] 不要跨线程访问共享变量 使共享变量是final类型的 将共享变量的操作加上同步 一开始就将类设计成线程安全的, 比在后期重新修复它,更容易. 编写多线...
  • fp196391196391
  • fp196391196391
  • 2014-09-23 08:41
  • 8361

java保证线程安全的两种方式

JVM有主内存(Main Memory)和工作内存(Working Memory),主内存就是平时所说的java堆内存,存放程序中所有的类实例、静态数据等变量,是线程共享的,而工作内存中存放的是从主内...
  • xiangxianghehe
  • xiangxianghehe
  • 2016-04-12 17:29
  • 6499

多线程编程-- 线程安全的栈 stack

首先看看 std::stack 容器的实现template<typename T,typename Container=std::deque > class stack { public: e...
  • u201012980
  • u201012980
  • 2016-07-31 10:47
  • 2211

4种方法实现线程安全

sychronized关键字    1. sychronized method(){}    2. sychronized (objectReference) {/*block*/} ...
  • lt26w
  • lt26w
  • 2015-03-16 14:46
  • 4538

Java多线程线程安全实现方式

线程安全就是要保证数据的高度一致性和准确性,但不是一定要加锁才是线程安全性,只要代码里没有变量互串,线程之间互不影响,就是线程安全的。 要了解线程安全,可以先看一下线程不安全是怎样的一种现象。pub...
  • YEN_CSDN
  • YEN_CSDN
  • 2016-06-17 19:38
  • 6818

(原创)确保JAVA线程安全的4种常用方法

在Java中可以有很多方法来保证线程安全,比如使用同步方法、同步块,使用原子类(atomic concurrent classes),实现并发锁,使用volatile关键字,使用不变类和线程安全类。 ...
  • starcrm
  • starcrm
  • 2016-09-18 17:38
  • 481
    QQ群
    读者交流群:189490960
    我的微信
      与本人单独交流~~
    个人资料
    • 访问:1409708次
    • 积分:22954
    • 等级:
    • 排名:第359名
    • 原创:466篇
    • 转载:7篇
    • 译文:9篇
    • 评论:1889条
    《C程序员从校园到职场》
    《信息通信技术百科全书》
    博客专栏
    博客已搬至微信公众号
    最新评论