线程同步基础

多个线程同时访问共享数据时可能会冲突。比如两个线程都要把某个全局变量增加1,这个操作在某平台需要三条指令完成:

1.从内存读变量值到寄存器
2.寄存器的值加1
3.将寄存器的值写回内存


 

假设两个线程在多处理器平台上同时执行这三条指令,则可能导致上图所示的结果,最后变量只加了一次而非两次


#include <stdio.h>
#include <stdlib.h>
#include <pthread.h>
#define NLOOP 1000

int counter; /* incremented by threads */
void *doit(void *);

int main(int argc, char **argv)
{
    pthread_t tidA, tidB;
    pthread_create(&tidA, NULL, &doit, NULL);
    pthread_create(&tidB, NULL, &doit, NULL);
    /* wait for both threads to terminate */
    pthread_join(tidA, NULL);
    pthread_join(tidB, NULL);
    return 0;
}
void *doit(void *vptr)
{
    int i, val;
    for (i = 0; i < NLOOP; i++)
    {
        val = counter;//1
        printf("%x: %d\n", (unsigned int)pthread_self(), val + 1);//2
        counter = val + 1;//3
    }
    return NULL;
} 

用注释中的1,2,3模拟三步指令

实验结果:

....

3dcac700: 1011
3dcac700: 1012
3dcac700: 1013
3dcac700: 1014
3dcac700: 1015
3dcac700: 1016
3dcac700: 1017
3dcac700: 1018
3dcac700: 1019
3dcac700: 1020
3dcac700: 1021

并没有加到2000



线程为什么要同步
1.共享资源,多个线程都可对共享资源操作
2.线程操作共享资源的先后顺序不确定
3.处理器对存储器的操作一般不是原子操作

解决办法:


#include <stdio.h>
#include <stdlib.h>
#include <pthread.h>
#define NLOOP 1000


pthread_mutex_t mutex = PTHREAD_MUTEX_INITIALIZER;
int counter; /* incremented by threads */
void *doit(void *);

int main(int argc, char **argv)
{
    pthread_t tidA, tidB;
    pthread_create(&tidA, NULL, &doit, NULL);
    pthread_create(&tidB, NULL, &doit, NULL);
    /* wait for both threads to terminate */
    pthread_join(tidA, NULL);
    pthread_join(tidB, NULL);
    return 0;
}
void *doit(void *vptr)
{
    int i, val;
    for (i = 0; i < NLOOP; i++) 
    {
        pthread_mutex_lock(&mutex);
        val = counter;
        printf("%x: %d\n", (unsigned int)pthread_self(), val + 1);
        counter = val + 1;
        pthread_mutex_unlock(&mutex);
    }
    return NULL;
}


死锁

1.同一个线程在拥有A锁的情况下再次请求获得A锁
2.线程一拥有A锁,请求获得B锁;线程二拥有B锁,请求获得A锁死锁导致的结果是什么?

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


pthread_mutex_t mutexA = PTHREAD_MUTEX_INITIALIZER;
pthread_mutex_t mutexB = PTHREAD_MUTEX_INITIALIZER;

int counter; /* incremented by threads */
void *doitA(void *);
void *doitB(void *);


int main(int argc, char **argv)
{
    pthread_t tidA, tidB;
    pthread_create(&tidA, NULL, &doitA, NULL);
    pthread_create(&tidB, NULL, &doitB, NULL);
    /* wait for both threads to terminate */
    pthread_join(tidA, NULL);
    pthread_join(tidB, NULL);
    return 0;
}
void *doitA(void *vptr)
{
    pthread_mutex_lock(&mutexA);
    printf("doitA:after lock A!\n");
    sleep(1);
    printf("doitA:before lock B!\n");
    pthread_mutex_lock(&mutexB);
    pthread_mutex_unlock(&mutexB);
    pthread_mutex_unlock(&mutexA);
    
    return NULL;
}

void *doitB(void *vptr)
{
  
  pthread_mutex_lock(&mutexB);
  printf("after lock B!\n");
  sleep(1);
  printf("before lock A!\n");
  pthread_mutex_lock(&mutexA);
  pthread_mutex_unlock(&mutexA);
  pthread_mutex_unlock(&mutexB);
  return NULL;
}


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值