重庆分公司,新征程启航
为企业提供网站建设、域名注册、服务器等服务
这篇文章给大家带来线程同步与互斥的学习!!!
这些名词,我们在共享内存中已经了解过⭐⭐
验证:设置一个多线程来进行抢票,票数为共享资源 – 售票系统代码
#include#include#include#includeusing namespace std;
int ticket = 10000;
void *GrabTickets(void *args)
{// 多线程一直抢票,直到票数<=0为止
const char *name = static_cast(args);
while (true)
{if (ticket >0)
{usleep(1000);
printf("%s: 抢到了票, 票的编号为: %d\n", name, ticket);
ticket--;
}
else
{printf("%s: 已经放弃抢票了,因为没有了...\n", name);
break;
}
}
return nullptr;
}
int main()
{// 定义线程id
pthread_t tid1;
pthread_t tid2;
pthread_t tid3;
pthread_t tid4;
// 创建线程
if (pthread_create(&tid1, nullptr, GrabTickets, (void *)"Thread1") != 0)
{exit(EXIT_FAILURE);
}
if (pthread_create(&tid2, nullptr, GrabTickets, (void *)"Thread2") != 0)
{exit(EXIT_FAILURE);
}
if (pthread_create(&tid3, nullptr, GrabTickets, (void *)"Thread3") != 0)
{exit(EXIT_FAILURE);
}
if (pthread_create(&tid4, nullptr, GrabTickets, (void *)"Thread4") != 0)
{exit(EXIT_FAILURE);
}
// 线程等待 -- 不获取线程退出码
pthread_join(tid1, nullptr);
pthread_join(tid2, nullptr);
pthread_join(tid3, nullptr);
pthread_join(tid4, nullptr);
return 0;
}
一次运行结果:出现溢出抢票的情况!!!
Thread3: 已经放弃抢票了,因为没有了...
Thread2: 抢到了票, 票的编号为: 3
Thread2: 已经放弃抢票了,因为没有了...
Thread4: 抢到了票, 票的编号为: -1
Thread4: 已经放弃抢票了,因为没有了...
Thread1: 抢到了票, 票的编号为: -2
Thread1: 已经放弃抢票了,因为没有了...
// 取出ticket--部分的汇编代码
// 指令:objdump -d a.o >test.objdump
//-------------------------------------------------------------------------------------
44: 8b 05 00 00 00 00 mov 0x0(%rip),%eax # 4a<_Z11GrabTicketsPv+0x4a>4a: 83 e8 01 sub $0x1,%eax
4d: 89 05 00 00 00 00 mov %eax,0x0(%rip) # 53<_Z11GrabTicketsPv+0x53>
为什么说ticket不是原子操作呢?
初始化互斥量有二种方法
第一种方法:静态分配
#includepthread_mutex_t mutex = PTHREAD_MUTEX_INITIALIZER;
第二个方法:动态分配
#includeint pthread_mutex_init(pthread_mutex_t *restrict mutex,
const pthread_mutexattr_t *restrictattr);
销毁互斥锁:
#include
加锁和解锁:
#include
调用 pthread_ lock 时,可能会遇到以下情况:⭐⭐
互斥量处于未锁状态,该函数会将互斥量锁定,同时返回成功
发起函数调用时,其他线程已经锁定互斥量,或者存在其他线程同时申请互斥量,但没有竞争到互斥量,那么pthread_ lock调用会陷入阻塞(执行流被挂起),等待互斥量解锁
修改前面的售票系统代码:使用动态分配互斥锁,需要释放互斥锁(pthread_mutex_destroy)
#include#include#include#includeusing namespace std;
// 1、定义互斥锁,主线程初始化
pthread_mutex_t Mutex;
int ticket = 10000;
void *GrabTickets(void *args)
{const char *name = static_cast(args);
while (true)
{// 3、加锁
pthread_mutex_lock(&Mutex);
if (ticket >0)
{usleep(1000);
printf("%s: 抢到了票, 票的编号为: %d\n", name, ticket);
ticket--;
// 解锁 -- 互斥量的粒度越细越好
pthread_mutex_unlock(&Mutex);
}
else
{// 解锁 -- 如果没有解锁,线程再次加锁时,会一直阻塞
pthread_mutex_unlock(&Mutex);
printf("%s: 已经放弃抢票了,因为没有了...\n", name);
break;
}
}
return nullptr;
}
int main()
{// 2、初始化互斥锁 -- 动态分配互斥锁
pthread_mutex_init(&Mutex, nullptr);
// 定义线程id
pthread_t tid1;
pthread_t tid2;
pthread_t tid3;
pthread_t tid4;
// 创建线程
if (pthread_create(&tid1, nullptr, GrabTickets, (void *)"Thread1") != 0)
{exit(EXIT_FAILURE);
}
if (pthread_create(&tid2, nullptr, GrabTickets, (void *)"Thread2") != 0)
{exit(EXIT_FAILURE);
}
if (pthread_create(&tid3, nullptr, GrabTickets, (void *)"Thread3") != 0)
{exit(EXIT_FAILURE);
}
if (pthread_create(&tid4, nullptr, GrabTickets, (void *)"Thread4") != 0)
{exit(EXIT_FAILURE);
}
// 线程等待 -- 不获取线程退出码
pthread_join(tid1, nullptr);
pthread_join(tid2, nullptr);
pthread_join(tid3, nullptr);
pthread_join(tid4, nullptr);
// 释放互斥锁 -- 动态申请的互斥锁
pthread_mutex_destroy(&Mutex);
return 0;
}
修改前面的售票系统代码:使用静态分配互斥锁,不需要释放互斥锁
#include#include#include#includeusing namespace std;
// 1、定义互斥锁,主线程初始化 -- 静态分配互斥锁
pthread_mutex_t Mutex = PTHREAD_MUTEX_INITIALIZER;
int ticket = 10000;
void *GrabTickets(void *args)
{const char *name = static_cast(args);
while (true)
{// 3、加锁
pthread_mutex_lock(&Mutex);
if (ticket >0)
{usleep(1000);
printf("%s: 抢到了票, 票的编号为: %d\n", name, ticket);
ticket--;
// 解锁 -- 互斥量的粒度越细越好
pthread_mutex_unlock(&Mutex);
}
else
{// 解锁 -- 如果没有解锁,线程再次加锁时,会一直阻塞
pthread_mutex_unlock(&Mutex);
printf("%s: 已经放弃抢票了,因为没有了...\n", name);
break;
}
}
return nullptr;
}
int main()
{// 2、初始化互斥锁
pthread_mutex_init(&Mutex, nullptr);
// 定义线程id
pthread_t tid1;
pthread_t tid2;
pthread_t tid3;
pthread_t tid4;
// 创建线程
if (pthread_create(&tid1, nullptr, GrabTickets, (void *)"Thread1") != 0)
{exit(EXIT_FAILURE);
}
if (pthread_create(&tid2, nullptr, GrabTickets, (void *)"Thread2") != 0)
{exit(EXIT_FAILURE);
}
if (pthread_create(&tid3, nullptr, GrabTickets, (void *)"Thread3") != 0)
{exit(EXIT_FAILURE);
}
if (pthread_create(&tid4, nullptr, GrabTickets, (void *)"Thread4") != 0)
{exit(EXIT_FAILURE);
}
// 线程等待 -- 不获取线程退出码
pthread_join(tid1, nullptr);
pthread_join(tid2, nullptr);
pthread_join(tid3, nullptr);
pthread_join(tid4, nullptr);
return 0;
}
临界区的临界资源被锁后,当前线程时间片到了,还能进行线程间切换吗?加锁 == 不会切换?⭐⭐⭐
比如:我们有线程A和其他线程
当执行完二条汇编语句时,时间片到了,线程切换后,会出问题吗?
当一个线程在执行时,CPU中一组寄存器中保存的值被称为该线程的上下文
如果多线程同时竞争锁时,同时将0数据传输到al寄存器中,会出现问题吗?
你是否还在寻找稳定的海外服务器提供商?创新互联www.cdcxhl.cn海外机房具备T级流量清洗系统配攻击溯源,准确流量调度确保服务器高可用性,企业级服务器适合批量采购,新人活动首月15元起,快前往官网查看详情吧