线程:
基本用法
-
线程和进程的虚拟地址空间不同。 区别。 线程的优点:切换 ,创造、资源更轻量, 进程中多个线程的共有数据 和 私有数据
-
pthread_detach 创建一个线程默认的状态是joinable, 如果一个线程结束运行但没有被join,则它的状态类似于进程中的Zombie Process,即还有一部分资源没有被回收(退出状态码),所以创建线程者应该调用pthread_join来等待线程运行结束,并可得到线程的退出代码,回收其资源(类似于wait,waitpid) 但是调用pthread_join(pthread_id)后,如果该线程没有运行结束,调用者会被阻塞,在有些情况下我们并不希望如此,比如在Web服务器中当主线程为每个新来的链接创建一个子线程进行处理的时候,主线程并不希望因为调用pthread_join而阻塞(因为还要继续处理之后到来的链接),这时可以在子线程中加入代码 pthread_detach(pthread_self()) 或者父线程调用 pthread_detach(thread_id)(非阻塞,可立即返回) 这将该子线程的状态设置为detached,则该线程运行结束后会自动释放所有资源。 或者创建的时候 create指定attr
To explicitly create a thread as detached, use the attr argument in pthread_create() •4 step process: 1) Declareapthreadattributevariableofthepthread_attr_t data type 2) Initializetheattributevariablewithpthread_attr_init() 3) Settheattributedetachedstatuswith pthread_attr_setdetachstate() 4) Whendone,freelibraryresourcesusedbytheattributewith pthread_attr_destroy()
- 加锁 typedef struct MyRecord { pthread_mutex_t myLock; int myValue; } MyRec;
void incrementRecordValue(MyRec* rec) { pthread_mutex_lock(&rec->myLock); rec->myValue = rec->myValue + 1; pthread_mutex_unlock(&rec->myLock); } Mutex Attributes
锁一个list, 为每个元素枷锁 typedef struct list_node_s { int data; struct list_node_s* next; pthread_mutex_t mutex; } LNode;
枷锁遍历元素的代码
-
生产者和消费者的模型 mutex lock 然后 while(!predict) wait_cond(cond1, muxtex); mutex unlock
-
spinlock
从实现原理上来讲,Mutex属于sleep-waiting类型的锁。例如在一个双核的机器上有两个线程(线程A和线程B),它们分别运行在Core0和 Core1上。假设线程A想要通过pthread_mutex_lock操作去得到一个临界区的锁,而此时这个锁正被线程B所持有,那么线程A就会被阻塞 (blocking),Core0 会在此时进行上下文切换(Context Switch)将线程A置于等待队列中,此时Core0就可以运行其他的任务(例如另一个线程C)而不必进行忙等待。而Spin lock则不然,它属于busy-waiting类型的锁,如果线程A是使用pthread_spin_lock操作去请求锁,那么线程A就会一直在 Core0上进行忙等待并不停的进行锁请求,直到得到这个锁为止。 function spinlock_lock(spinlock_t* mx) { while (test_and_set(mx) == 1); } function spinlock_unlock(spinlock_t* mx) { *mx = 0; } rw lock Barriers
- 死锁 tls cancel Priority
- 线程 伪共享
#include <pthread.h>
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <string.h>
#define NUM_THREADS 8
struct thread_data {
int thread_num;
char* message;
int len;
};
void* PrintHello(void* threadarg) {
struct thread_data* my_data = (struct thread_data*) threadarg;
sleep(1 + 5 * (my_data->thread_num % 2));
my_data->len = strlen(my_data->message);
printf("Thread #%d: %s length=%d\n", my_data->thread_num, my_data->message,
my_data->len);
pthread_exit(NULL);
}
int main(int argc, char* argv[]) {
pthread_t threads[NUM_THREADS];
struct thread_data thread_data_array[NUM_THREADS];
char* messages[NUM_THREADS];
int rc, t;
messages[0] = "English: Hello World!";
messages[1] = "French: Bonjour, le monde!";
messages[2] = "Spanish: Hola al mundo";
messages[3] = "Klingon: Nuq neH!";
messages[4] = "German: Guten Tag, Welt!";
messages[5] = "Russian: Zdravstvuyte, mir!";
messages[6] = "Japan: Sekai e konnichiwa!";
messages[7] = "Latin: Orbis, te saluto!";
for (t = 0; t < NUM_THREADS; t++) {
thread_data_array[t].thread_num = t;
thread_data_array[t].message = messages[t];
printf("Creating thread #%d\n", t);
rc = pthread_create(&threads[t], NULL, PrintHello,
&thread_data_array[t]);
if (rc) {
printf("ERROR; return code from pthread_create() is %d\n", rc);
exit(-1);
}
}
int grand_total = 0;
for (t = 0; t < NUM_THREADS; t++) {
printf("Joining thread #%d\n", t);
rc = pthread_join(threads[t], NULL);
if (rc) {
printf("ERROR; return code from pthread_join() is %d\n", rc);
exit(-1);
}
grand_total += thread_data_array[t].len;
}
printf("Grand total = %d\n", grand_total);
pthread_exit(NULL);
}