在线程应用中,常常会遇到数据的共享问题,利用互斥锁可以有效解决。下面以程序为例:
1.
#include<stdio.h>
#include<osapi/osapi.h>
char g_key[16]; // Generator更新它,Checker获取它
class KeyGenerator : public OS_Thread{
private:virtual int Routine(){
int times=0;
while(1){
for(int i=0;i<16;i++){
g_key[i]=times;
}
times++;
if(times>=128)times=0;
OS_Thread::Msleep(50);
}
return 0;
}
};
class KeyChecker : public OS_Thread{
private:
virtual int Routine(){
while(1){
for(int i=1;i<16;i++){
if(g_key[i]!=g_key[i-1]){
printf("不完整!!\n");
printKey();
return 0;
}
}
OS_Thread::Msleep(50);
}
return 0;//正常退出
}
void PrintKey()
{
printf("Key: ");
for(int i=0; i<16; i++)
printf("%02X ", g_key[i]);
printf("\n");
}
};
int main(){//容易出现问题
KeyGenerator a;
a.Run();
KeyChecker b;
b.Run();
getchar();
return 0;
}
2.利用互斥锁
//#define _CRT_SECURE_NO_WARNINGS /* VS2013,2015需要这一行 */
#include <stdio.h>
#include "osapi/osapi.h"
OS_Mutex g_mutex;
char g_key[16]; // Generator更新它,Checker获取它
class KeyGenerator : public OS_Thread
{
private:
virtual int Routine()
{
int times = 0;
while(1)
{
// 更新key
g_mutex.Lock();
for(int i=0; i<16; i++)
{
OS_Thread::Msleep(5);
g_key[i] = times;
}
g_mutex.Unlock();
times ++;
if(times >= 128) times = 0;
//OS_Thread::Msleep(50);
}
return 0;
}
};
class KeyChecker : public OS_Thread
{
private:
// 线程主函数
virtual int Routine()
{
while(1)
{
// 数据处理
// 检查完整性
g_mutex.Lock();
for(int i=1; i<16; i++)
{
if(g_key[i] != g_key[i-1])
{
printf("不完整!!\n");
PrintKey();
//return 0;
}
}
g_mutex.Unlock();
//OS_Thread::Msleep(50);
}
return 0; // 正常退出
}
void PrintKey()
{
printf("Key: ");
for(int i=0; i<16; i++)
printf("%02X ", g_key[i]);
printf("\n");
}
};
int main()
{
KeyGenerator a;
a.Run();
KeyChecker b;
b.Run();
getchar();
return 0;
}
3.改进代码
利用拷贝机制,减少了锁机制的应用时间,避免了线程的无限等待。
#include<stdio.h>
#include "osapi/osapi.h"
OS_Mutex g_mutex;//锁机制使用时间不能太长
char g_key[16];
class KeyGenerator :public OS_Thread
{
private:
virtual int Routine(){int times = 0;
while(1)
{
// 生成key: 需要80ms
char key_new[16];
for(int i=0; i<16; i++)
{
OS_Thread::Msleep(5);
key_new[i] = times;
}
// 更新key: 占有锁的时间非常短
g_mutex.Lock();
memcpy(g_key, key_new, 16);
g_mutex.Unlock();
times ++;
if(times >= 128) times = 0;
//OS_Thread::Msleep(50);
printf("写!");
}
return 0;
}
};
class KeyChecker : public OS_Thread
{
private:
// 线程主函数
virtual int Routine()
{
while(1)
{
// 尽量缩短对共享数据的访问时间
char copy[16];
g_mutex.Lock();
memcpy(copy, g_key, 16);
g_mutex.Unlock();
// 数据处理
// 检查完整性
for(int i=1; i<16; i++)
{
if(copy[i] != copy[i-1])
{
printf("不完整!!\n");
PrintKey();
//return 0;
}
} printf("读!\n");
//OS_Thread::Msleep(50);
}
return 0; // 正常退出
}
void PrintKey()
{
printf("Key: ");
for(int i=0; i<16; i++)
printf("%02X ", g_key[i]);
printf("\n");
}
};
int main(){
KeyGenerator mytask1;
mytask1.Run();
KeyChecker mytask2;
mytask1.Run();
getchar();
return 0;
}
1.
#include<stdio.h>
#include<osapi/osapi.h>
char g_key[16]; // Generator更新它,Checker获取它
class KeyGenerator : public OS_Thread{
private:virtual int Routine(){
int times=0;
while(1){
for(int i=0;i<16;i++){
g_key[i]=times;
}
times++;
if(times>=128)times=0;
OS_Thread::Msleep(50);
}
return 0;
}
};
class KeyChecker : public OS_Thread{
private:
virtual int Routine(){
while(1){
for(int i=1;i<16;i++){
if(g_key[i]!=g_key[i-1]){
printf("不完整!!\n");
printKey();
return 0;
}
}
OS_Thread::Msleep(50);
}
return 0;//正常退出
}
void PrintKey()
{
printf("Key: ");
for(int i=0; i<16; i++)
printf("%02X ", g_key[i]);
printf("\n");
}
};
int main(){//容易出现问题
KeyGenerator a;
a.Run();
KeyChecker b;
b.Run();
getchar();
return 0;
}
2.利用互斥锁
//#define _CRT_SECURE_NO_WARNINGS /* VS2013,2015需要这一行 */
#include <stdio.h>
#include "osapi/osapi.h"
OS_Mutex g_mutex;
char g_key[16]; // Generator更新它,Checker获取它
class KeyGenerator : public OS_Thread
{
private:
virtual int Routine()
{
int times = 0;
while(1)
{
// 更新key
g_mutex.Lock();
for(int i=0; i<16; i++)
{
OS_Thread::Msleep(5);
g_key[i] = times;
}
g_mutex.Unlock();
times ++;
if(times >= 128) times = 0;
//OS_Thread::Msleep(50);
}
return 0;
}
};
class KeyChecker : public OS_Thread
{
private:
// 线程主函数
virtual int Routine()
{
while(1)
{
// 数据处理
// 检查完整性
g_mutex.Lock();
for(int i=1; i<16; i++)
{
if(g_key[i] != g_key[i-1])
{
printf("不完整!!\n");
PrintKey();
//return 0;
}
}
g_mutex.Unlock();
//OS_Thread::Msleep(50);
}
return 0; // 正常退出
}
void PrintKey()
{
printf("Key: ");
for(int i=0; i<16; i++)
printf("%02X ", g_key[i]);
printf("\n");
}
};
int main()
{
KeyGenerator a;
a.Run();
KeyChecker b;
b.Run();
getchar();
return 0;
}
3.改进代码
利用拷贝机制,减少了锁机制的应用时间,避免了线程的无限等待。
#include<stdio.h>
#include "osapi/osapi.h"
OS_Mutex g_mutex;//锁机制使用时间不能太长
char g_key[16];
class KeyGenerator :public OS_Thread
{
private:
virtual int Routine(){int times = 0;
while(1)
{
// 生成key: 需要80ms
char key_new[16];
for(int i=0; i<16; i++)
{
OS_Thread::Msleep(5);
key_new[i] = times;
}
// 更新key: 占有锁的时间非常短
g_mutex.Lock();
memcpy(g_key, key_new, 16);
g_mutex.Unlock();
times ++;
if(times >= 128) times = 0;
//OS_Thread::Msleep(50);
printf("写!");
}
return 0;
}
};
class KeyChecker : public OS_Thread
{
private:
// 线程主函数
virtual int Routine()
{
while(1)
{
// 尽量缩短对共享数据的访问时间
char copy[16];
g_mutex.Lock();
memcpy(copy, g_key, 16);
g_mutex.Unlock();
// 数据处理
// 检查完整性
for(int i=1; i<16; i++)
{
if(copy[i] != copy[i-1])
{
printf("不完整!!\n");
PrintKey();
//return 0;
}
} printf("读!\n");
//OS_Thread::Msleep(50);
}
return 0; // 正常退出
}
void PrintKey()
{
printf("Key: ");
for(int i=0; i<16; i++)
printf("%02X ", g_key[i]);
printf("\n");
}
};
int main(){
KeyGenerator mytask1;
mytask1.Run();
KeyChecker mytask2;
mytask1.Run();
getchar();
return 0;
}