目录
相关函数列表
注意事项
一个创建线程的例子
用clone函数实现线程
线程互斥的例子
带超时的互斥程序
读写锁的例子
一个条件变量的例子(可用于生产者-消费者模式)
自旋锁
barrier模式
进程和线程原语的比较
参考
//对两个线程ID进行比较
//若相等返回非0数值,否则返回0
#include
int pthread_equal(pthread_t tid1, pthread_t tid2);
//获得线程自身的ID
#include
pthread_t pthread_self(void);
//创建新线程
//pthread_attr_t用来定制各种不同的线程属性,新线程函数从start_rtn函数的地址开始运行,如果
//要向start_rtn传递参数,需要将这些参数放入结构体中,然后将此将结构体地址作为arg参数传入
#include
int pthread_create(pthread_t *restrict tidp, const pthread_attr_t *restrict attr,
void *(*strt_rtn)(void *), void *restrict arg);
//单个线程可以通过3种方式退出
//1.线程可以简单地从启动例程种返回,返回值是线程的退出码
//2.线程可以被同一进程中的其他线程取消
//3.线程调用pthread_exit
#include
void pthread_exit(void *rval_ptr);
//进程中的其他线程可以通过调用下列函数来访问这个 rval_ptr指针
//如果对线程的返回值不感兴趣,可以把rval_ptr设置为NULL,这样等于等待线程终止,但是不获取
//线程终止状态
#include
int pthread_join(pthread_t thread, void **rval_ptr);
//线程取消
#include
int pthread_cancel(pthread_t tid);
//可以安排一些清理函数,类似进程的atexit函数,这样的函数被称为线程清理处理程序(thread
//cleanup handler),一个线程可以建立多个清理处理程序,其执行顺序和注册顺序相反
#include
void pthread_cleanup_push(void (*rtn)(void *), void *arg);
void pthread_cleanup_pop(int execute);
//分离线程
#include
int pthread_detach(pthread_t tid);
//互斥量
//如果不希望被阻塞使用trylock函数,不出现阻塞直接返回0,否则就会失败不能锁住返回EBUSY
//timelock函数指定一个绝对时间(在X到达之前可以阻塞,而不是等待Y秒)
#include
int pthread_mutex_init(pthread_mutex_t *restrict mutex, const pthread_mutexattr_t *restrict attr);
int pthread_mutex_destroy(pthread_mutex_t *mutex);
int pthread_mutex_lock(pthread_mutex_t *mutex);
int pthread_mutex_trylock(pthread_mutex_t *mutex);
int pthread_mutex_unlock(pthread_mutex_t *mutex);
int pthread_mutex_timedlock(pthread_mutex_t *restrict mutex, const struct timespec *restrict tsptr);
//读写锁
#include
int pthread_rwlock_init(pthread_rwlock_t *restrict rwlock);
int pthread_rwlock_destroy(pthread_rwlock_t *rwlock);
int pthread_rwlock_rdlock(pthread_rwlock_t *rwlock);
int pthread_rwlock_wrlock(pthread_rwlock_t *rwlock);
int pthread_rwlock_unlock(pthread_rwlock_t *rwlock);
int pthread_rwlock_tryrdlock(pthread_rwlock_t *rwlock);
int pthread_rwlock_trywrlock(pthread_rwlock_t *rwlock);
int pthread_rwlock_timerdlock(pthread_rwlock_t *restrict rwlock, const struct
timespec *restrict tsptr);
int pthread_rwlock_timewrlock(pthread_rwlock_t *restrict rwlock, const struct
timespec *restrict tsptr);
//条件变量
#include
int pthread_cond_init(pthread_cond_t *restrict cond, const pthread-condattr_t *restrict attr);
int pthread_cond_destroy(pthread_cond_t *cond);
int pthread_cond_wait(pthread_cond_t *restrict cond, pthread_mutex *restrict mutex);
int pthread_cond_timedwait(pthread_cond_t *restrict cond, pthread_mutex_t *restrict mutex,
const struct timespec *restrict tsptr);
int pthread_cond_signal(pthread_cond_t *cond);
int pthread_cond_broadcast(pthread_cond_t *cond);
//自旋锁
#include
int pthread_spin_init(pthread_spinlock_t *lock, int pshared);
int pthread_spin_destroy(pthread_spinlock_t *lock);
int pthread_spin_lock(pthread_spinlock_t *lock);
int pthread_spin_trylock(pthread_spinlock_t *lock);
int pthread_spin_unlock(pthread_spinlock_t *lock);
//屏障
#include
int pthread_barrier_init(pthread_barrier_t *restrict barrier, const pthread_barrierattr_t
*restrict attr, unsigned int count);
int pthread_barrier_destroy(pthred_barrier_t *barrier);
int pthread_barrier_wait(pthread_barrier_t *barrier);
不要用直接操作pthread_t结构体
这样会导致代码不可移植,初始化结构体后,用相关函数操作
同样,pthread.h中的其他结构体也不要直接操作,初始化好之后用相关函数操作
因为pthread不是linux的标准库,所以GCC编译时,需要加上 -lpthread参数
#include
#include
#include
void clearn(void *msg) {
printf("clean %s\n",(char*)msg);
}
//线程回调函数f1
void *f1(void *arg) {
printf("thread f1 startup...\n");
//注册一个清理函数
pthread_cleanup_push(clearn,"f1-> 11111");
pthread_cleanup_push(clearn,"f1-> 22222");
if(arg) {
return ((void *)1);
}
//删除清理hook
pthread_cleanup_pop(0);
pthread_cleanup_pop(0);
return ((void *)1);
}
//线程回调函数f1
void *f2(void *arg) {
printf("thread f2 startup...\n");
pthread_cleanup_push(clearn,"f2-> 11111");
pthread_cleanup_push(clearn,"f2-> 22222");
if(arg) {
pthread_exit((void *)2);
}
pthread_cleanup_pop(0);
pthread_cleanup_pop(0);
pthread_exit((void*)2);
return ((void *)2);
}
int main(int argc, char *argv[]) {
pthread_t p1,p2;
void* ret;
//在main中创建两个线程
pthread_create(&p1,NULL,f1,(void*)1);
pthread_create(&p2,NULL,f2,(void*)2);
//main线程join,等待线程f1的结束
pthread_join(p1,&ret);
printf("thread 1 exit code %d\n",ret);
pthread_join(p2,&ret);
printf("thread 2 exit code %d\n",ret);
}
//编译
gcc -lpthread -o p2 p2.c
//执行结果
thread f1 startup...
thread 1 exit code 1
thread f2 startup...
clean f2-> 22222
clean f2-> 11111
thread 2 exit code 2
//用strace分析程序
//pthread_create是用clone实现的,pthread_join是用futex实现的
...
clone(child_stack=0x7f852e106fb0, flags=CLONE_VM|CLONE_FS|CLONE_FILES|CLONE_SIGHAND|CLONE_THREAD|CLONE_SYSVSEM|CLONE_SETTLS|CLONE_PARENT_SETTID|CLONE_CHILD_CLEARTID, parent_tidptr=0x7f852e1079d0, tls=0x7f852e107700, child_tidptr=0x7f852e1079d0) = 13937
futex(0x7f852e9089d0, FUTEX_WAIT, 13936, NULLstrace: Process 13936 attached
...
java中创建线程也是用clone实现的,线程之间的同步也是用futex实现的,因为最终调用的c的函数
#include
#include /* For SYS_xxx definitions */
#include
#include
#include
#include
#include
#include
#include
#include
#define STACK_SIZE 1024*1024*8
int thread_func(void *lparam) {
printf("thread id %d \n", (int)syscall(SYS_gettid));
printf("thread get param : %d \n", (int*)lparam);
sleep(1);
return 0;
}
void child_handler(int sig) {
printf("I got a SIGCHLD\n");
}
int main(int argc, char **argv) {
setvbuf(stdout, NULL, _IONBF, 0);
signal(SIGCHLD, child_handler);
void *pstack = (void *)mmap(NULL,
STACK_SIZE,PROT_READ | PROT_WRITE ,
MAP_PRIVATE | MAP_ANONYMOUS | MAP_ANON ,//| MAP_GROWSDOWN ,
-1,
0);
if (MAP_FAILED != pstack) {
int ret;
printf("strace addr : 0x%X\n", (int*)pstack);
ret = clone(thread_func,
(void *)((unsigned char *)pstack + STACK_SIZE),
CLONE_VM | CLONE_FS | CLONE_THREAD | CLONE_FILES | CLONE_SIGHAND | SIGCHLD,
(void *)NULL);
if (-1 != ret) {
pid_t pid = 0;
printf("start thread %d \n", ret);
sleep(5);
pid = waitpid(-1, NULL, __WCLONE | __WALL);
printf("child : %d exit %s\n", pid,strerror(errno));
}
else {
printf("clone failed %s\n", strerror(errno) );
}
}
else {
printf("mmap() failed %s\n", strerror(errno));
}
return 0;
}
#include
#include
#include
#include
pthread_mutex_t mutex;
int num = 100;
void lock() {
pthread_mutex_lock(&mutex);
}
void unlock() {
pthread_mutex_unlock(&mutex);
}
void *f1(void *msg) {
lock();
sleep(3);
num++;
unlock();
printf("11111111111111 ok\n");
pthread_exit(NULL);
}
void *f2(void *msg) {
lock();
sleep(2);
num++;
unlock();
printf("222222222222222 ok\n");
pthread_exit(NULL);
}
int main(int argc, char *argv[]) {
pthread_t p1,p2;
void *ret1,*ret2;
pthread_mutex_init(&mutex,NULL);
pthread_create(&p1,NULL,f1,(void*)1);
pthread_create(&p2,NULL,f2,(void*)2);
pthread_join(p1,&ret1);
pthread_join(p2,&ret2);
pthread_mutex_destroy(&mutex);
printf("num=%d\n",num);
}
//执行结果
11111111111111 ok
222222222222222 ok
num=102
//strace分析程序
clone(child_stack=0x7fa128e6efb0, flags=CLONE_VM|CLONE_FS|CLONE_FILES|CLONE_SIGHAND|CLONE_THREAD|CLONE_SYSVSEM|CLONE_SETTLS|CLONE_PARENT_SETTID|CLONE_CHILD_CLEARTID, parent_tidptr=0x7fa128e6f9d0, tls=0x7fa128e6f700, child_tidptr=0x7fa128e6f9d0) = 14611
...
clone(child_stack=0x7fa12866dfb0, flags=CLONE_VM|CLONE_FS|CLONE_FILES|CLONE_SIGHAND|CLONE_THREAD|CLONE_SYSVSEM|CLONE_SETTLS|CLONE_PARENT_SETTID|CLONE_CHILD_CLEARTID, parent_tidptr=0x7fa12866e9d0, tls=0x7fa12866e700, child_tidptr=0x7fa12866e9d0) = 14612
...
futex(0x7fa128e6f9d0, FUTEX_WAIT, 14611, NULLstrace: Process 14611 attached
...
[pid 14611] futex(0x6010a0, FUTEX_WAKE_PRIVATE, 1) = 1
[pid 14612] futex(0x6010a0, FUTEX_WAKE_PRIVATE, 1) = 0
[pid 14612] write(1, "222222222222222 ok\n", 19222222222222222 ok
) = 19
//madvise()这个函数可以对映射的内存提出使用建议,从而提高内存。
[pid 14612] madvise(0x7fa127e6e000, 8368128, MADV_DONTNEED) = 0
...
#include
#include
#include
#include
#include
#define false 0
#define true 1
#define bool int
pthread_mutex_t mutex;
void lock() {
pthread_mutex_lock(&mutex);
}
void unlock() {
pthread_mutex_unlock(&mutex);
}
bool lock_timeout(int second) {
struct timespec tout;
clock_gettime(CLOCK_REALTIME,&tout);
tout.tv_sec += second;
int err;
err = pthread_mutex_timedlock(&mutex,&tout);
if(err == 0) {
printf("mutex lock ok!\n");
return true;
} else {
printf("mutex lock failure!\n");
return false;
}
}
void *f1(void *arg) {
lock();
sleep(10);
printf("f1...\n");
unlock();
pthread_exit(NULL);
}
void *f2(void *arg) {
sleep(2);
if(lock_timeout(3)) {
printf("f2 ok...\n");
} else {
printf("f2 failure\n");
}
unlock();
pthread_exit(NULL);
}
int main(int argc, char *argv[]) {
pthread_t p1,p2;
void *ret1,*ret2;
pthread_mutex_init(&mutex,NULL);
pthread_create(&p1,NULL,f1,(void*)1);
pthread_create(&p2,NULL,f2,(void*)2);
pthread_join(p1,&ret1);
pthread_join(p2,&ret2);
pthread_mutex_destroy(&mutex);
printf("main ok...\n");
}
//运行结果
mutex lock failure!
f2 failure
f1...
main ok...
//用strace分析程序
//超时也是用futex实现的
。。。
futex(0x6010c0, FUTEX_WAIT_BITSET_PRIVATE|FUTEX_CLOCK_REALTIME, 2, {1541943304, 588528513}, ffffffff) = -1 ETIMEDOUT (Connection timed out)
fstat(1, {st_mode=S_IFCHR|0620, st_rdev=makedev(136, 1), ...}) = 0
mmap(NULL, 4096, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_ANONYMOUS, -1, 0) = 0x7f0257e05000
write(1, "mutex lock failure!\n", 20mutex lock failure!) = 20
write(1, "f2 failure\n", 11f2 failure) = 11
。。。
#include
#include
#include
#include
#include
#define false 0
#define true 1
#define bool int
pthread_rwlock_t rw_lock;
void read_lock() {
pthread_rwlock_rdlock(&rw_lock);
}
void write_lock() {
pthread_rwlock_wrlock(&rw_lock);
}
void unlock() {
pthread_rwlock_unlock(&rw_lock);
}
void *f1_r(void *arg) {
read_lock();
sleep(5);
printf("f1_r ok\n");
unlock();
pthread_exit(NULL);
}
void *f2_r(void *arg) {
read_lock();
sleep(3);
printf("f2_r ok\n");
unlock();
pthread_exit(NULL);
}
void *f3_w(void *arg) {
sleep(1);
write_lock();
sleep(2);
printf("f3_w ok\n");
unlock();
pthread_exit(NULL);
}
int main(int argc, char *argv[]) {
pthread_t p1,p2,p3;
void *ret1, *ret2, *ret3;
pthread_rwlock_init(&rw_lock,NULL);
pthread_create(&p1,NULL,f1_r,(void*)1);
pthread_create(&p2,NULL,f2_r,(void*)2);
pthread_create(&p3,NULL,f3_w,(void*)3);
pthread_join(p1,&ret1);
pthread_join(p2,&ret2);
pthread_join(p3,&ret3);
pthread_rwlock_destroy(&rw_lock);
return 0;
}
//执行结果
f2_r ok
f1_r ok
f3_w ok
//用strace分析
...
会出现三次clone函数调用
...
futex(0x7f4797f54190, FUTEX_WAKE_PRIVATE, 2147483647) = 0
write(1, "f1_r ok\n", 8f1_r ok) = 8
futex(0x6010ac, FUTEX_WAKE_PRIVATE, 1
...
#include
#include
#include
#include
#include
#include
#define false 0
#define true 1
#define bool int
pthread_mutex_t mutex;
pthread_cond_t cond;
char *msg;
void lock() {
pthread_mutex_lock(&mutex);
}
void unlock() {
pthread_mutex_unlock(&mutex);
}
void wait() {
pthread_cond_wait(&cond,&mutex);
}
void signal() {
pthread_cond_signal(&cond);
}
void signal_all() {
pthread_cond_broadcast(&cond);
}
void *f1() {
lock();
sleep(5);
if( strcmp(msg,"ok") ==0 ) {
printf("f1... strcmp ok\n");
signal();
}
else {
printf("f1... not equals set -> ok\n");
memcpy(msg,"ok",2);
}
unlock();
pthread_exit(NULL);
}
void *f2() {
lock();
sleep(3);
if( strcmp(msg,"ok") != 0 ) {
printf("f2... strcmp not equals\n");
wait();
}
else {
printf("f2... equals\n");
signal();
}
unlock();
pthread_exit(NULL);
}
int main(int argc, char *argv[]) {
pthread_t p1,p2;
void *ret1, *ret2;
msg = (char*)malloc(sizeof(char)*10);
pthread_create(&p1,NULL,f1,(void*)1);
pthread_create(&p2,NULL,f2,(void*)2);
pthread_join(p1,&ret1);
pthread_join(p2,&ret2);
pthread_cond_destroy(&cond);
pthread_rwlock_destroy(&mutex);
printf("end main...\n");
return 0;
}
//执行结果
f1... not equals set -> ok
f2... equals
end main...
//用strace分析程序,也是用futex实现的
...
futex(0x6020c0, FUTEX_WAKE_PRIVATE, 1) = 1
...
futex(0x7f443a27a9d0, FUTEX_WAIT, 19266, NULL
...
#include
#include
#include
#include
#include
#include
#define false 0
#define true 1
#define bool int
pthread_spinlock_t mutex;
int num =0;
void lock() {
pthread_spin_lock(&mutex);
}
void try_lock() {
pthread_spin_trylock(&mutex);
}
void unlock() {
pthread_spin_unlock(&mutex);
}
void *f1(void *msg) {
int i=0;
for(;i<10;i++) {
lock();
num++;
unlock();
}
printf("f1 ok\n");
pthread_exit(NULL);
}
void *f2(void *msg) {
int i=0;
for(;i<100;i++) {
lock();
num++;
unlock();
}
printf("f2 ok\n");
pthread_exit(NULL);
}
int main(int argc, char *argv[]) {
pthread_t p1,p2;
void *ret1, *ret2;
pthread_spin_init(&mutex,PTHREAD_PROCESS_PRIVATE);
pthread_create(&p1,NULL,f1,(void*)1);
pthread_create(&p2,NULL,f2,(void*)2);
printf("##################################################");
pthread_join(p1,&ret1);
pthread_join(p2,&ret2);
pthread_spin_destroy(&mutex);
printf("num -> %d\n",num);
return 0;
}
#include
#include
#include
#include
#include
#include
#define false 0
#define true 1
#define bool int
pthread_barrier_t barrier;
pthread_mutex_t mutex;
pthread_cond_t cond;
int barrier_num = 3;
int num;
void lock() {
pthread_mutex_lock(&mutex);
}
void unlock() {
pthread_mutex_unlock(&mutex);
}
void *f1() {
lock();
num++;
barrier_num--;
unlock();
printf("f1 ok %x\n",pthread_self());
pthread_barrier_wait(&barrier);
if(barrier_num==0) {
printf("f1 notify\n");
pthread_cond_signal(&cond);
}
pthread_exit(NULL);
}
void *f2() {
lock();
num++;
barrier_num--;
unlock();
printf("f2 ok %x\n",pthread_self());
pthread_barrier_wait(&barrier);
if(barrier_num==0) {
printf("f2 notify\n");
pthread_cond_signal(&cond);
}
pthread_exit(NULL);
}
void *f3() {
lock();
num++;
barrier_num--;
unlock();
printf("f3 ok %x\n",pthread_self());
pthread_barrier_wait(&barrier);
if(barrier_num==0) {
printf("f3 notify\n");
pthread_cond_signal(&cond);
}
pthread_exit(NULL);
}
void *reduce() {
printf("pre reduce\n");
lock();
printf("reduce wait\n");
pthread_cond_wait(&cond,&mutex);
unlock();
printf("reduce sum -> %d\n",num);
}
int main(int argc, char *argv[]) {
pthread_t p1,p2,p3,p4;
void *ret1, *ret2, *ret3, *ret4;
pthread_mutex_init(&mutex,NULL);
pthread_barrier_init(&barrier,NULL,barrier_num);
pthread_create(&p1,NULL,f1,(void*)1);
pthread_create(&p2,NULL,f2,(void*)2);
pthread_create(&p3,NULL,f3,(void*)3);
pthread_create(&p4,NULL,reduce,(void*)4);
pthread_join(p1,&ret1);
pthread_join(p2,&ret2);
pthread_join(p3,&ret3);
pthread_join(p4,&ret4);
pthread_mutex_destroy(&mutex);
pthread_barrier_destroy(&barrier);
printf("main end... %x\n",pthread_self());
return 0;
}
//运行结果
f1 ok 86c7f700
f2 ok 8647e700
f3 ok 85c7d700
f3 notify
pre reduce
reduce wait
f2 notify
reduce sum -> 3
f1 notify
main end... 87474740
进程原语 | 线程原语 | 描述 |
fork | pthread_create | 创建新的控制流 |
exit | pthread_exit | 从现有的控制流中退出 |
waitpid | pthread_join | 从控制流中得到退出状态 |
atexit | pthread_cancel_push | 注册在退出控制流时调用的函数 |
getpid | pthread_self | 获取控制流的ID |
abort | pthread_cancel | 请求控制流的非正常退出 |
undefined reference to 'pthread_create'问题解决
Linux 中使用 clone 函数来创建线程
Linux 中使用 clone 函数
futex 手册摘要
threadpool —— 基于 pthread 实现的简单线程池