项目3 多线程并发锁
本专栏知识点是通过<零声教育>的系统学习,进行梳理总结写下文章,对c/c++linux课程感兴趣的读者,可以点击链接,详细查看详细的服务:链接
多线程并发介绍
多线程是为了 让程序更加速度,上面是多线程的流程
编译的时候
对于含有<pthread.h>的程序:
在编译的时候需要加上额外的参数-lpthread,因为该头文件在Linux默认Import Library中没有,需要使用库libpthread.a进行编译链接。
gcc -o lock lock.c -lpthread
实现原理
主函数中的 pthread_create 调用用于创建线程。它接受四个参数:第一个参数是要创建的线程的ID,使用 &threadid[i] 获取线程ID的地址;第二个参数为线程属性,这里设置为 NULL;第三个参数是线程回调函数,即 thread_callback;第四个参数是传递给线程回调函数的参数,这里传递了指向 count 变量的指针。
#include <stdio.h>
#include <pthread.h>
#include <unistd.h>
#define THREAD_COUNT 10
void *thread_callback(void *arg){
int *pcount = (int *)arg; // 接收线程数
int i = 0;
while (i++< 100000){
(*pcount)++;
usleep(1);
}
}
int main() {
pthread_t threadid[THREAD_COUNT] = {0};
int i = 0;
int count=0;
for (i = 0; i < THREAD_COUNT; i++) {
pthread_create(&threadid[i],NULL, thread_callback,&count);
}
for (i = 0; i < 100; i++) {
printf("count :%d\n",count);
sleep(1);
}
return 0;
}
count 是临界资源
锁区别
自旋锁和 互斥锁区别:
什么时候使用:
锁的内容少,可以用自旋锁
锁的内容比较多,用互斥锁 可以节省
自旋锁:
while(1) 等待结果, 释放之后再立即执行
互斥锁:
引起现成切换,不会循环,如果占用就让出现成等待
互斥锁
相当于把 代码川起来,运行完这个就锁死 ,下一个再来
void *thread_callback(void *arg){
int *pcount = (int *)arg;
int i = 0;
while (i++< 100000){
#if 0
(*pcount)++;
#else
pthread_mutex_lock(&mutex);
(*pcount)++;
pthread_mutex_unlock(&mutex);
#endif
usleep(1);
}
}
自旋锁
spinlock
进程共用
pthread_spinlock_t spinlock; //声明 自旋锁
使用:
pthread_spin_lock(&spinlock);
(*pcount)++;
pthread_spin_unlock(&spinlock);
原子操作
最好的实现方式
多条指令 变成一条指令,单条cpu 指令实现
实现一个函数 调用
int inc(int *value,int add){
int old;
__asm__ volatile(
"lock; xaddl %2, %1;"
: "=a" (old)
: "m" (*value),"a"(add)
: "cc","memory"
);
return old;
}
汇编代码执行以下步骤:
lock; xaddl %2, %1; - 这条指令执行原子交换操作。它将add参数中的值加到*value指向的内存位置上,并将之前的值存储在old变量中。lock前缀确保该指令以原子方式执行。
内联汇编代码使用了多个输入输出操作数:
"=a" (old) - old是一个输出操作数,之前的值存储在eax寄存器中。
"m" (*value) - *value是一个输入输出操作数,表示由value指向的内存位置。
"a" (add) - add是一个输入操作数,其值加载到eax寄存器中。
cas 实现
和其他锁其实一样,都是先加锁 确定线程完事,对比状态,一段线程结束释放,进入下一个线程
#define LOCK_STATE_OK 0
#define LOCK_STATE_LOCKED 100、
//声明 cas 锁
atomic_int lock = ATOMIC_VAR_INIT(LOCK_STATE_OK);
void acquire_lock(){
int expected = LOCK_STATE_OK;
int desired = LOCK_STATE_LOCKED;
int success = __sync_bool_compare_and_swap(&lock, expected, desired);
while (!success) {
// 获取锁失败时的自旋等待
expected = LOCK_STATE_OK;
success = __sync_bool_compare_and_swap(&lock, expected, desired);
}
}
//释放锁
void release_lock() {
//printf("Releasing lock...\n");
lock = 0;
}
//使用的时候
void *thread_callback(void *arg){
int *pcount = (int *)arg;
int i = 0;
while (i++< 100000){
acquire_lock(pcount);
(*pcount)++;
release_lock();
}
}