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 7 exception
MODULE 7 Exceptions---------------------------- 程序正常执行过程中遇到的意外情况 引发异常的因素: 1)程序本身的内在因素 2)外部因素引发的,程序无须 ...
- extjs实现多国语音切换
http://kuyur.info/blog/archives/2490 http://blog.chinaunix.net/uid-28661623-id-3779637.html http://b ...
- MVC 中的@Html.DropDownList下拉框的使用
MVC 中的下拉框 实现方式,下面为大家介绍一个我自己认为比较好用的实现方式,而二话不说直接上代码: 第一步: 后台代码 //公共的方法 //在每次需要展示下拉框的时候,需要调用一下这个方法 [数据源 ...
- Visio编辑数据库模型列
Visio编辑数据库模型列:邮件group->Open实体,进入实体属性编辑界面,按回车可以添加.
- Qt使用QStackedWidget实现堆栈窗口
Qt使用QStackedWidget实现堆栈窗口 分类: QT2012-07-25 21:59 6997人阅读 评论(0) 收藏 举报 qtlistsignal 堆栈窗口可以根据选择项的不同显示不同的 ...
- java implement
接口不能被实例化,但是可以声明一个接口类型的变量. eg. A implements B,则可以有B variableName = new A(),这和extends的用法是类似的 接口可被认为是纯抽 ...
- Machine Learning 学习笔记 (2) —— 使用牛顿法寻找极值
本系列文章允许转载,转载请保留全文! [请先阅读][说明&总目录]http://www.cnblogs.com/tbcaaa8/p/4415055.html 1. 用牛顿法解方程 牛顿法是一种 ...
- 一个Option请求引发的深度解析
在当前项目中,前端通过POST方式访问后端的REST接口时,发现两条请求记录,一条请求的Request Method为Options,另一条请求的Reuest Method为Post.想要解决这个疑惑 ...
- “我爱淘”冲刺阶段Scrum站立会议7
完成任务: 大事不好,今天的任务还没有完成,没有通过xml文件通过服务器显示到软件中. 计划任务: 实现通过服务器将xml文件中的数据显示到软件中. 遇到问题: 服务器已经配好,并且解析xml文件的代 ...
- C#开源大全--汇总(转)
商业协作和项目管理平台-TeamLab 网络视频会议软件-VMukti 驰骋工作流程引擎-ccflow [免费]正则表达式测试工具-Regex-Tester Windows-Phone-7-SDK E ...