#include
#include
#include
#include
#include
//准备创建16个线程
#define PTHREAD_NUM 16
//一个全局变量
unsigned long sum = 0;
void *thread(void *arg)
{
for(int i = 0;i < 10000; i++)
{
sum += 1;
}
}
int main(void)
{
printf("before,sum = %ld\n",sum);
pthread_t pthread[PTHREAD_NUM];//pthread是指向进程标识符的指针
int ret;//接收返回值
void *retval[PTHREAD_NUM];
for(int i = 0 ;i < PTHREAD_NUM; ++i)
{
ret = pthread_create(&pthread[i],NULL,thread,NULL);
if(ret != 0)
{
perror("cause:");
printf("创建第%d个线程失败\n",i+1);
}
}
for(int i = 0; i < PTHREAD_NUM; ++i)
{
pthread_join(pthread[i],&retval[i]);
}
printf("after,sum = %ld\n",sum);
printf("Goodbye!\n");
return 0;
}
①额外注释
pthread_create()第一个参数为指向线程标识符的指针。
第二个参数用来设置线程属性。
第三个参数是线程运行函数的起始地址。
最后一个参数是运行函数的参数。
pthread_join()函数,以阻塞的方式等待thread指定的线程结束。
当函数返回时,被等待线程的资源被收回。如果线程已经结束,那么该函数会立即返回。
并且thread指定的线程必须是joinable的。
②解析:这段代码没有利用原子操作或加锁操作,所以跑起来的结果,sum的值不一定是预期的160000,如图:
还是先看代码
#include
#include
#include
#include
#include
//准备创建16个线程
#define PTHREAD_NUM 16
//一个全局变量
unsigned long sum = 0;
void *thread(void *arg)
{
for(int i = 0;i < 10000; i++)
{
//这一行是原子操作
__sync_fetch_and_add (&sum,1);//这行代码的注释单独放在下文
}
}
int main(void)
{
printf("before,sum = %ld\n",sum);
pthread_t pthread[PTHREAD_NUM];//pthread是指向进程标识符的指针
int ret;//接收返回值
void *retval[PTHREAD_NUM];
for(int i = 0 ;i < PTHREAD_NUM; ++i)
{
ret = pthread_create(&pthread[i],NULL,thread,NULL);
if(ret != 0)
{
perror("cause:");
printf("创建第%d个线程失败\n",i+1);
}
}
for(int i = 0; i < PTHREAD_NUM; ++i)
{
pthread_join(pthread[i],&retval[i]);
}
printf("after,sum = %ld\n",sum);
printf("Goodbye!\n");
return 0;
}
①__sync_fetch_and_add (&sum,1);
这行代码的解析
这个系列的函数
type __sync_fetch_and_add (type *ptr, type value);
type __sync_fetch_and_sub (type *ptr, type value);
type __sync_fetch_and_or (type *ptr, type value);
type __sync_fetch_and_and (type *ptr, type value);
type __sync_fetch_and_xor (type *ptr, type value);
type __sync_fetch_and_nand (type *ptr, type value);
type __sync_add_and_fetch (type *ptr, type value);
type __sync_sub_and_fetch (type *ptr, type value);
type __sync_or_and_fetch (type *ptr, type value);
type __sync_and_and_fetch (type *ptr, type value);
type __sync_xor_and_fetch (type *ptr, type value);
type __sync_nand_and_fetch (type *ptr, type value);
参考资料: linux无锁化编程–__sync_fetch_and_add系列原子操作函数
用法是这样的,这个系列的函数看函数名我们就能猜出函数的功能。
比如说
type __sync_fetch_and_add (type *ptr, type value);
这个函数接受一个type 类型的指针ptr和type类型的数值value,执行对ptr执行的对象进行加value的操作。
因此,我们这行代码就是对全局变量sum进行效果是“sum+=1”的原子操作
__sync_fetch_and_add (&sum,1);
②ok,运行结果如我们所预期的,sum最后值都是160000
注意,g++编译命令要加-std=c++11
这个参数
老规矩,看代码,跟上面大同小异
#include
#include
#include
#include
#include
//定义一个互斥量mymutex
pthread_mutex_t mymutex=PTHREAD_MUTEX_INITIALIZER;
//准备创建16个线程
#define PTHREAD_NUM 16
//一个全局变量
unsigned long sum = 0;
void *thread(void *arg)
{
for(int i = 0;i < 10000; i++)
{
//上锁
pthread_mutex_lock(&mymutex);
sum += 1;
//解锁
pthread_mutex_unlock(&mymutex);
}
}
int main(void)
{
printf("before,sum = %ld\n",sum);
pthread_t pthread[PTHREAD_NUM];//pthread是指向进程标识符的指针
int ret;//接收返回值
void *retval[PTHREAD_NUM];
for(int i = 0 ;i < PTHREAD_NUM; ++i)
{
ret = pthread_create(&pthread[i],NULL,thread,NULL);
if(ret != 0)
{
perror("cause:");
printf("创建第%d个线程失败\n",i+1);
}
}
for(int i = 0; i < PTHREAD_NUM; ++i)
{
pthread_join(pthread[i],&retval[i]);
}
printf("after,sum = %ld\n",sum);
printf("Goodbye!\n");
return 0;
}