Linux多线程之互斥
题目
共要卖票20张,由命令行输入窗口数,由线程模拟窗口。每卖掉一张票,屏幕显示由几号窗口所卖,一并显示剩余票数
思路
由于票数 ticket_cnt 是全局变量,因此每当一个线程将其减一(卖出一张票),并将其显示,应该被封装为一个原子操作。因为线程是并发执行的,可能当前线程将ticket_cnt减1后还没有来得及显示此时的剩余票数ticket_cnt,ticket_cnt已经被另一个线程减一了。此处通过互斥锁实现互斥。
函数原型
创建线程:
NAME
pthread_create - create a new thread SYNOPSIS
#include <pthread.h> int pthread_create(pthread_t *thread, const pthread_attr_t *attr,
void *(*start_routine) (void *), void *arg); Compile and link with -pthread.
回收线程资源,该函数为阻塞函数。
NAME
pthread_join - join with a terminated thread SYNOPSIS
#include <pthread.h> int pthread_join(pthread_t thread, void **retval); Compile and link with -pthread. DESCRIPTION
The pthread_join() function waits for the thread specified
by thread to terminate. If that thread has already termi-
nated, then pthread_join() returns immediately. The thread
specified by thread must be joinable. If retval is not NULL, then pthread_join() copies the exit
status of the target thread (i.e., the value that the tar-
get thread supplied to pthread_exit(3)) into the location
pointed to by *retval. If the target thread was canceled,
then PTHREAD_CANCELED is placed in *retval. If multiple threads simultaneously try to join with the
same thread, the results are undefined. If the thread
calling pthread_join() is canceled, then the target thread
will remain joinable (i.e., it will not be detached). RETURN VALUE
On success, pthread_join() returns 0; on error, it returns
an error number.
解锁开锁
NAME
pthread_mutex_lock
pthread_mutex_unlock - lock and unlock a mutex SYNOPSIS
#include <pthread.h> int pthread_mutex_lock(pthread_mutex_t *mutex);
int pthread_mutex_unlock(pthread_mutex_t *mutex);
初始化锁,销毁锁
NAME
pthread_mutex_destroy, pthread_mutex_init - destroy and initialize a mutex SYNOPSIS
#include <pthread.h> int pthread_mutex_destroy(pthread_mutex_t *mutex);
int pthread_mutex_init(pthread_mutex_t *restrict mutex, const pthread_mutexattr_t *restrict attr);
代码
/*************************************************************************
> File Name: ticket.c
> Author: KrisChou
> Mail:zhoujx0219@163.com
> Created Time: Mon 25 Aug 2014 07:40:38 PM CST
************************************************************************/ #include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <pthread.h> int ticket_cnt = 20; /* 共有20张票 */
typedef struct tag
{
int s_id;
pthread_mutex_t *s_p;
}DATA,*pDATA; void* handler(void *arg )
{
int id = ((pDATA)arg)->s_id;
pthread_mutex_t *p_mutex = ((pDATA)arg)-> s_p;
printf("a window on !: %d \n", id);
while(1)
{
pthread_mutex_lock(p_mutex);
if(ticket_cnt == 0)
{
printf("ticket out! \n");
pthread_mutex_unlock(p_mutex);
free((pDATA)arg);
return (void*)0;
}
--ticket_cnt;
sleep(rand()%3 + 1);
printf("window: %d : a ticket sold. left : %d \n", id,ticket_cnt );
pthread_mutex_unlock(p_mutex);
sleep(rand() % 3 + 1); /* 如果不sleep,锁会一直被这个执行完的线程所占据 */ }
} int main(int argc, char *argv[])
{
srand(getpid());
pthread_mutex_t mutex;
pthread_mutex_init(&mutex, NULL);
int thd_cnt = atoi(argv[1]); /* 从命令行输入卖票窗口数 */
pthread_t *tds = (pthread_t*)calloc(thd_cnt,sizeof(pthread_t));
int index;
for(index = 0; index < thd_cnt; index++ )
{
pDATA p = (pDATA)calloc(1,sizeof(DATA));
p->s_id = index;
p->s_p = &mutex;
pthread_create(tds + index , NULL,handler,(void*)p);
}
printf("joining...\n");
for(index = 0; index < thd_cnt; index++)
{
pthread_join(tds[index],NULL);
}
pthread_mutex_destroy(&mutex);
return 0;
}
编译运行:
[purple@localhost review]$ gcc ticket.c -lpthread
[purple@localhost review]$ ./a.out 5
joining...
a window on !: 2
a window on !: 3
a window on !: 4
a window on !: 1
a window on !: 0
window: 2 : a ticket sold. left : 19
window: 3 : a ticket sold. left : 18
window: 4 : a ticket sold. left : 17
window: 1 : a ticket sold. left : 16
window: 0 : a ticket sold. left : 15
window: 2 : a ticket sold. left : 14
window: 3 : a ticket sold. left : 13
window: 4 : a ticket sold. left : 12
window: 1 : a ticket sold. left : 11
window: 0 : a ticket sold. left : 10
window: 2 : a ticket sold. left : 9
window: 3 : a ticket sold. left : 8
window: 4 : a ticket sold. left : 7
window: 1 : a ticket sold. left : 6
window: 0 : a ticket sold. left : 5
window: 2 : a ticket sold. left : 4
window: 3 : a ticket sold. left : 3
window: 4 : a ticket sold. left : 2
window: 1 : a ticket sold. left : 1
window: 0 : a ticket sold. left : 0
ticket out!
ticket out!
ticket out!
ticket out!
ticket out!
干货
如果有一个整型参数 a 需要在创建线程时将其传递给线程,那么以下两种传值方式,实际上是由区别的。来看代码:
方式1:
void* handler(void *arg)
{
int val=*(int*)arg;
printf("from main: %d\n",val);
pthread_exit((void*)"hello world");
}
int main()
{
pthread_t thd;
int a=12345;
pthread_create(&thd,NULL,handler,(void*)&a);
printf("thd: %x\n",thd);
pthread_join(thd,(void*)&ret);
return 0;
}
方式2:
void* handler(void *arg)
{
int val=(int)arg;
printf("from main: %d\n",val);
pthread_exit((void*)"hello world");
}
int main()
{
pthread_t thd;
int a=12345;
pthread_create(&thd,NULL,handler,(void*)a);
printf("thd: %x\n",thd);
pthread_join(thd,(void*)&ret);
return 0;
}
对于方式1,传给handler的参数是a的地址,如果a的值之后在主线程里会发生变化,那么传给handler的数值a可能就不是原来我们想传的那个了。
而对于方式2,由于是值传递,我们当时想传什么,传到handler中的就一定是什么。
由此可见,虽然方式1节省了存储空间,但是同样也容易发生错误。
Linux多线程之互斥的更多相关文章
- Linux多线程——使用互斥量同步线程
前文再续,书接上一回,在上一篇文章: Linux多线程——使用信号量同步线程中,我们留下了一个如何使用互斥量来进行线程同步的问题,本文将会给出互斥量的详细解说,并用一个互斥量解决上一篇文章中,要使用两 ...
- Linux多线程--使用互斥量同步线程【转】
本文转载自:http://blog.csdn.net/ljianhui/article/details/10875883 前文再续,书接上一回,在上一篇文章:Linux多线程——使用信号量同步线程中, ...
- Linux多线程--使用信号量同步线程【转】
本文转载自:http://blog.csdn.net/ljianhui/article/details/10813469 信号量.同步这些名词在进程间通信时就已经说过,在这里它们的意思是相同的,只不过 ...
- [转]一个简单的Linux多线程例子 带你洞悉互斥量 信号量 条件变量编程
一个简单的Linux多线程例子 带你洞悉互斥量 信号量 条件变量编程 希望此文能给初学多线程编程的朋友带来帮助,也希望牛人多多指出错误. 另外感谢以下链接的作者给予,给我的学习带来了很大帮助 http ...
- Linux多线程(三)(同步互斥)
1. 线程的同步与互斥 1.1. 线程的互斥 在Posix Thread中定义了一套专门用于线程互斥的mutex函数.mutex是一种简单的加锁的方法来控制对共享资源的存取,这个互斥锁只有两种状态(上 ...
- Linux多线程服务端编程一些总结
能接触这本书是因为上一个项目是用c++开发基于Linux的消息服务器,公司没有使用第三方的网络库,卷起袖子就开撸了.个人因为从业经验较短,主 要负责的是业务方面的编码.本着兴趣自己找了这本书.拿到书就 ...
- linux多线程同步pthread_cond_XXX条件变量的理解
在linux多线程编程中,线程的执行顺序是不可预知的,但是有时候由于某些需求,需要多个线程在启动时按照一定的顺序执行,虽然可以使用一些比较简陋的做法,例如:如果有3个线程 ABC,要求执行顺序是A-- ...
- Linux多线程编程和Linux 2.6下的NPTL
Linux多线程编程和Linux 2.6下的NPTL 在Linux 上,从内核角度而言,基本没有什么线程和进程的区别--大家都是进程.一个进程的多个线程只是多个特殊的进程他们虽然有各自的进程描述结构, ...
- linux多线程编程(转)
原文地址:http://www.cnblogs.com/BiffoLee/archive/2011/11/18/2254540.html 1.Linux“线程” 进程与线程之间是有区别的,不过Linu ...
随机推荐
- core java 1~4(HelloWorld & 标识符|关键字|数据类型 & 表达式|流程控制 & 数组)
MODULE 1 Java的编译和运行----------------------------编译:javac -d bin src\HelloWorld.java -d:指定编译后的class 文件 ...
- JavaScript高级程序设计之基本包装类型
为便于操作基本类型值,ECMAScript提供了3个特殊的引用类型:Boolean, Number 和 String // 字符串怎么会有方法呢 var str1 = "some text& ...
- 基于Elasticsearch的自定义评分算法扩展
实现思路: 重写评分方法,调整计算文档得分的过程,然后根据function_score或script_sort进行排序检索. 实现步骤: 1.新建java项目TestProject,引入Elast ...
- zeromq
分布式系统之分布式中间件zeroMQ zeroMQ,又称0MQ,是一个非常简单的通信库,它扩展了传统BSD socket能力,提供简单的基于消息的通信.zeroMQ不解析消息体,没有序列化能力,或者说 ...
- 通过store为toolbar添加按钮
目的是实现导航条toolbar可以动态加载按钮. ExtJS的版本是4.0. 实现方案有两个.方案一:添加render事件监听,在监听事件处理函数中使用Ext.Ajax获取按钮信息,实现动态添加按钮. ...
- 失败的数据库迁移UDB
公司采用的是ucloud的云主机,数据库也是架设在云主机上.由于数据越来越多数据查询数据越来越慢,所以我决定往 UDB上迁移.当时考虑的理由如下: (1)云主机底层架设在虚拟机上IO性能有折损,而UD ...
- activemq整合spring
- 微软职位内部推荐-SDEII for Windows Phone Apps
微软近期Open的职位: Job title: Software Design Engineer II Location: China, Beijing Division: Operations Sy ...
- js之基本包装类型
为了便于操作“基本类型值”,JS 提供了 三个 特殊的引用类型:Boolean.Number.String.这些类型和其他引用类型相似,但同时 也具备 与各自基本类型相应的特殊行为. 实际上:每当读取 ...
- opencv 2.4.9+pcl 1.6+vs2010+win7 32开发环境配置
最近在做图像方面的开发,需要对软件开发平台进行配置,我查找了关于这些方面的内容,由于软件版本很多,每个人的开发平台又不一样所以在对平台进行搭建过程中遇到了很多问题,下面我将我搭建平台的流程做一个记录. ...