什么代码才是线程安全的

转自:http://www.cnblogs.com/lidabo/archive/2013/04/10/3011518.html

对于多线程编程,很多人概念不清,写代码的时候要么是处处加锁,影响性能不说,还容易莫名其妙的死锁,还有人对多线程敬而远之。

所以学习多线程编程最重要的不是学习API,而是理解什么才是多线程安全的代码

从例子说起

#include <windows.h>
#include <process.h>

long global1 = 0;
volatile long global2 = 0;

class MyClass
{
public:
    MyClass() : m(0)
    {
        ++m;
    }

    int fun(int v)
    {
        return m+v; //-----------9
    }

    void set(int v)
    {
        m = v;   //-------------10
    }
    int m;
};

MyClass global_object; //-------------8

unsigned int __stdcall thread_fun1(void *param)
{
    static int static2 = 0;
    static MyClass static_object; //--------6
    int local1 = 0;

    ++local1;     //-------1
    ++static2;    //-------2
    ++global1;    //-------3
    ++global2;    //-------4
    InterlockedIncrement(&global1); //--------5

    local1 = global_object.fun(local1); //----------7

    global_object.set(local1); //---------------11

    return 0;
}

unsigned int __stdcall thread_fun2(void *param)
{
    ++global1;    //-------3
    ++global2;    //-------4
    InterlockedIncrement(&global1); //--------5

    global_object.set(1); //-----------11
    return 0;
}

int main()
{
    HANDLE thread1 = (HANDLE)_beginthreadex(0,0,&thread_fun1,0,0,0); //thread 1
    HANDLE thread2 = (HANDLE)_beginthreadex(0,0,&thread_fun1,0,0,0); //thread 2
    HANDLE thread3 = (HANDLE)_beginthreadex(0,0,&thread_fun2,0,0,0); //thread 3

    WaitForSingleObject(thread1,INFINITE);
    WaitForSingleObject(thread2,INFINITE);
    WaitForSingleObject(thread3,INFINITE);

    return 0;
}

1.局部变量局部使用是安全的
为什么?因为每个thread 都有自己的运行堆栈,而局部变量是生存在堆栈中,大家不干扰。
所以代码1
int local1;
++local1;
是安全的

2.全局原生变量多线程读写是不安全的
全局变量是在堆(heap)中
long global1 = 0;
++global2;
++这个操作其实分为两部,一个是读,另外一个是写
 mov         ecx,global
 add         ecx,1
 mov         global,ecx
所以代码3处是不安全的

3.函数静态变量多线程读写也是不安全的
道理同2
所以代码2处也是不安全的

4.volatile能保证全局整形变量是多线程安全的么
不能。
volatile仅仅是告诫compiler不要对这个变量作优化,每次都要从memory取数值,而不是从register
所以代码4也不是安全

5.InterlockedIncrement保证整型变量自增的原子性
所以代码5是安全的

6.function static object的初始化是多线程安全的么
不是。
著名的Meyer Singleton其实不是线程安全的
Object & getInstance()

     static Object o;
     return o;
}
可能会造成多次初始化对象
所以代码6处是不安全的

7.在32机器上,4字节整形一次assign是原子的
比如
i =10; //thread1
i=4; //thread2
不会导致i的值处于未知状态,要么是10要么是4

写好多线程安全的法宝就是封装,使数据有保护的被访问到
安全性:
局部变量>成员变量>全局变量

时间: 2024-11-03 19:10:15

什么代码才是线程安全的的相关文章

PyQt4转换ui为py文件需添加如下代码才可执行

1)转换ui为py 命令行进入ui文件所在文件夹,输入pyuic4 ui_name.ui > py_name.py即可 或新建ui2py.bat文件,写入: @echo off @cd /d "%~dp0" pyuic4 %1 > %~n1.py 将ui文件拖入批处理即可,生成在ui文件所在目录,文件名为py_name.py 2)转换后的py文件还不能运行,需要可视化操作才可运行 具体见帖:http://www.cnblogs.com/doudongchun/p/36947

究竟怎样写代码才算是好代码

今天让我们来谈谈代码吧.代码重要吗?当然,代码就是设计(Jack W.Reeves, 1992):代码是最有价值的交付物.我们需要好代码吗?在给"好代码"下个定义之前,这个问题无法回答.那么,究竟什么是好代码? 看下面这段英文解释: 'Good code' is code that works, is bug free, and is readable and maintainable. Some organizations have coding 'standards' that a

“整洁可用”的代码才算是好代码

之前有人问我,什么样的代码才算是好代码?一时语塞,百度后,我觉得这个是我觉得我想要的结果,来源https://wenku.baidu.com/view/8646287bf56527d3240c844769eae009581ba2e8.html 原文地址:https://www.cnblogs.com/suola/p/9546682.html

55行代码实现Java线程死锁

死锁是Java多线程的重要概念之一,也经常出现在各大公司的笔试面试之中.那么如何创造出一个简单的死锁情况?请看代码: class Test implements Runnable { boolean flag; Test(boolean flag) { this.flag = flag; } public void run() { if(flag) { while(true) //这里用while(true)使得线程在这里无限循环,可以避免各种随机情况造成死锁不成功 synchronized(M

什么样的代码才是好代码

衡量代码的好坏的指标或者维度有很多,比如性能好.架构好.高内聚等,这些指标的侧重点各不相同,不同的开发人员的关注的重点也各不相同.我个人更喜欢简单的可读性高的代码,我主要从以下几个维度衡量代码是否良好: 代码是可工作的 代码是可读性高的 代码是简单的 代码是高内聚的 代码是低耦合的 代码是可工作的 写代码的目的是要为了解决特定问题的,因此无论如何,代码首先是可工作的,能解决特定的问题.可工作的包含有两层含义:一是从功能角度来说能满足用户的需求,二是从性能角度来说要满足当前基本的性能需求.所以可工

一道自己看了代码才明白的简单构造

//codeforces 520c //思路:两个字符串,第一个字符串不动,移动第二个的时候,你会发现第二个串的每个字符都会和第一个串的某个字符对一次,所以在构造的时候当然选择出现次数最多的那个 //如果假设次数出现最多的字符有k种,第一个字符有k种选择,第二个有k种选择....第n个字符有k种选择, //rk(k,n); #include<iostream>  using namespace std;  #define M 1000000007;  int n;  char a[100010

深入谈谈Java最简单的单例设计模式

单例设计模式是23种设计模式里面最简单的,但是要彻底理解单例,还是需要下一点功夫的. 单例一般会分为饿汉模式和懒汉模式 饿汉模式: 1 public class Singleton 2 { 3 private static Singleton singleton = new Singleton(); 4 5 public static Singleton getInstance() 6 { 7 return singleton; 8 } 9 } 但是在一些系统应用环境中,这个单例对象可能比较大,

【java并发】(2) Java线程同步:synchronized锁住的是代码还是对象

在Java中,synchronized关键字是用来控制线程同步的,就是在多线程的环境下,控制synchronized代码段不被多个线程同时执行.synchronized既可以加在一段代码上,也可以加在方法上. 关键是,不要认为给方法或者代码段加上synchronized就万事大吉,看下面一段代码: class Sync { public synchronized void test() { System.out.println("test开始.."); try { Thread.sle

深入解析父子线程(父子线程相互独立,子线程使用自己的栈空间,进程要等到所有线程终止运行之后才终止运行)

说起多线程,我们可以说起一大堆和它相关的有趣话题来,比如什么子孙线程关系,父子线程关系,线程同步异步之类的研究话题来,而我今天所说的,是关于父子线程的一些有趣现象. 首先提出一个问题,“在多线程的应用程序中,当父线程结束之后,子线程会不会退出呢?”,本文将围绕这个问题,深入分析windows中父子线程的生命周期及他们之间的关系. 我们知道,不管你使用的是何种编程语言,但当我们在windows下编程,且使用了平台相关性的库的时候,不管我们使用什么函数来创建线程,最终的结果是,我们的代码中都会调用C