线程安全学习

1 什么是线程

线程是cpu调度的最小单位,在Linux 下 实现线程的方式为轻量级进程,复用进程的结构体,使用clone函数创建

2 线程安全

所谓线程安全,更确切的应该描述为内存安全

#include <stdio.h>
#include <pthread.h>
int a=1;
void* myfun(){

for(int i=0;i<10000;i++){
    a++;
    }
}

int main(){

pthread_t t1, t2;
pthread_create(&t1, NULL,myfun, (void*)1);
pthread_create(&t2, NULL, myfun, (void*)2);
pthread_join(t1, NULL);
pthread_join(t2, NULL);


}

上述代码 按照预期应该是 a++20000次,而执行结果却与预期不符,这就是典型的线程不安全

产生原因也很简单,在现代操作系统下 cpu并不是直接访问内存,每个cpu核心都有一个 独立的L0 L1 缓存,以及共享的L2 缓存,在线程1 将 a 从主存写入缓存时,进行++操作,此时a +1 并未回写至主存, 此时线程2 去主存中读取的值仍然为1, 并且 ++操作也非原子操作,多种可能都会导致结果不符合预期

如何实现线程安全

实现的方式有很多种

最简单常见的为使用二进制信号量或者mutex,例如

#include <stdio.h>
#include <pthread.h>
#include <semaphore.h>

//sem_t semaphore;//定义信号量
pthread_mutex_t mutex;
int a=1;
void* myfun(){

for(int i=0;i<10000;i++){
pthread_mutex_lock(&mutex);
//sem_wait(&semaphore);
    a++;
pthread_mutex_unlock(&mutex);
//sem_post(&semaphore);
return NULL;
    }
}

int main(){

//sem_init(&semaphore, 0, 1);
pthread_t t1, t2;
pthread_create(&t1, NULL,myfun, (void*)1);
pthread_create(&t2, NULL, myfun, (void*)2);
pthread_join(t1, NULL);
pthread_join(t2, NULL);

//sem_destroy(&semaphore);
pthread_mutex_destroy(&mutex)

}

semaphore 与 mutex 在底层由硬件cpu的原子指令以及缓存一致性协议与内存屏障保证其原子性

二者简单差异 为 semaphore 竞争失败时线程处于自旋状态,而mutex则让出cpu,增加了更多的上线文切换

在java 中常见的 synchronized 以及LOCK 都是使用mutex实现,例如

public class createFun {
    public static final Integer integer =1;
    public static int a=0;
    public static void main(String[] args) throws Exception{
        Thread t1= new Thread(new Runnable() {
            @Override
            public void run() {
                add();
            }
        });
        Thread t2= new Thread(new Runnable() {
            @Override
            public void run() {
                add();
            }
        });
        t1.start();
        t2.start();
        t1.join();
        t2.join();
        System.out.println("a="+a);
    }
    public  static void add(){
        for(int i=0;i<10000;i++) {
            synchronized (integer) {
                a++;
            }
        }
    }
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值