嵌入式应用开发基础-多线程编程
代码
p_thread1-创建线程
#include <pthread.h>
#include <unistd.h>
#include <stdio.h>
static void *my_thread_func (void *data)
{
while(1)
{
sleep(1);
}
}
int main(int argc, char** argv)
{
pthread_t tid;
int iRet;
/* 1. 创建"接收线程" */
iRet = pthread_create(&tid, NULL, my_thread_func, NULL);
if (iRet)
{
printf("pthread create err\n");
return -1;
}
/* 2. 主线程读取标准输入,发给"接收线程" */
while(1)
{
sleep(1);
}
return 0;
}
p_thread2-自实现同步操作
#include <pthread.h>
#include <unistd.h>
#include <stdio.h>
static char g_buf[1000];
static int g_hasData = 0;
static void *my_thread_func (void *data)
{
while(1)
{
/* 等待通知 */
#if 0
if (g_hasData == 1)
{
printf("recv: %s\n", g_buf);
}
/* 打印 */
#else
while(g_hasData == 0);
printf("recv: %s\n", g_buf);
#endif
g_hasData = 0;
}
}
int main(int argc, char** argv)
{
pthread_t tid;
int iRet;
/* 1. 创建"接收线程" */
iRet = pthread_create(&tid, NULL, my_thread_func, NULL);
if (iRet)
{
printf("pthread create err\n");
return -1;
}
/* 2. 主线程读取标准输入,发给"接收线程" */
while(1)
{
fgets(g_buf, 1000, stdin);
/* 通知接收线程 */
g_hasData = 1;
}
return 0;
}
- 在实际测试过程中,接收线程中用if()代替while()进行查询,发现输入并没有打印在屏幕上,原因应该是g_buf一直在被置零,两个线程都可以对g_hasData进行操作,会发生争抢,互相干扰,可以用互斥锁解决。
- 使用while()时,top命令查看资源占用情况,CPU资源占用率将近为100%,因为while()一直在执行,所以这里需要一个没检测到就休眠的信号量。
p_thread3-信号量同步
#include <pthread.h>
#include <unistd.h>
#include <stdio.h>
#include <semaphore.h>
static char g_buf[1000];
static int g_hasData = 0;
static sem_t g_sem;
static void *my_thread_func (void *data)
{
while(1)
{
/* 等待信号量 */
sem_wait(&g_sem);
/* 打印 */
printf("recv: %s\n", g_buf);
g_hasData = 0;
}
}
int main(int argc, char** argv)
{
pthread_t tid;
int iRet;
/* 1. 创建"接收线程" */
iRet = pthread_create(&tid, NULL, my_thread_func, NULL);
if (iRet)
{
printf("pthread create err\n");
return -1;
}
sem_init(&g_sem,0,0);
/* 2. 主线程读取标准输入,发给"接收线程" */
while(1)
{
if(fgets(g_buf, 1000, stdin) != NULL)
{
/* 释放信号量 */
sem_post(&g_sem);
}
}
return 0;
}
三个函数 sem_init();sem_post();sem_wait(),让top中找不到线程资源
- 可能存在的问题
在打印buffer的过程中,如果又输入了新的数据,则很有可能存在新旧数据重叠问题,故需要互斥量来保证不同线程的互相干扰问题
p_thread4-信号量同步、互斥锁
#include <pthread.h>
#include <unistd.h>
#include <stdio.h>
#include <semaphore.h>
static char g_buf[1000];
static sem_t g_sem;
static pthread_mutex_t g_tMutex = PTHREAD_MUTEX_INITIALIZER;
static void *my_thread_func (void *data)
{
while(1)
{
/* 等待信号量 */
sem_wait(&g_sem);
/* 打印 */
pthread_mutex_lock(&g_tMutex);
printf("recv: %s\n", g_buf);
pthread_mutex_unlock(&g_tMutex);
}
}
int main(int argc, char** argv)
{
pthread_t tid;
int iRet;
/* 1. 创建"接收线程" */
iRet = pthread_create(&tid, NULL, my_thread_func, NULL);
if (iRet)
{
printf("pthread create err\n");
return -1;
}
sem_init(&g_sem,0,0);
/* 2. 主线程读取标准输入,发给"接收线程" */
while(1)
{
if(fgets(g_buf, 1000, stdin) != NULL)
{
pthread_mutex_lock(&g_tMutex);
/* 释放信号量 */
sem_post(&g_sem);
pthread_mutex_unlock(&g_tMutex);
}
}
return 0;
}
- 互斥锁占用时间问题
在测试过程中,如果写成这个形式,互斥锁会一直被主进程获得,信号量刚刚释放,还没有被接收线程获得就又一次进入while循环,互斥锁又被主进程获得,打印不出信息
while(1)
{
pthread_mutex_lock(&g_tMutex);
fgets(g_buf, 1000, stdin) != NULL
pthread_mutex_unlock(&g_tMutex);
/* 释放信号量 */
sem_post(&g_sem);
}
更改为以下方式
while(1)
{
if(fgets(g_buf, 1000, stdin) != NULL)
{
pthread_mutex_lock(&g_tMutex);
/* 释放信号量 */
sem_post(&g_sem);
pthread_mutex_unlock(&g_tMutex);
}
}
避免主线程占用互斥锁的时间过长
p_thread5-条件同步、互斥锁
#include <pthread.h>
#include <unistd.h>
#include <stdio.h>
#include <semaphore.h>
static char g_buf[1000];
static pthread_mutex_t g_tMutex = PTHREAD_MUTEX_INITIALIZER;
static pthread_cond_t g_tConVar = PTHREAD_COND_INITIALIZER;
static void *my_thread_func (void *data)
{
while(1)
{
/* 获取互斥锁 */
pthread_mutex_lock(&g_tMutex);
/* 等待条件成立,条件成立执行接下来的代码,条件不成立释放互斥锁,继续等待 */
pthread_cond_wait(&g_tConVar, &g_tMutex);
/* 打印 */
printf("recv: %s\n", g_buf);
pthread_mutex_unlock(&g_tMutex);
}
}
int main(int argc, char** argv)
{
pthread_t tid;
int iRet;
/* 1. 创建"接收线程" */
iRet = pthread_create(&tid, NULL, my_thread_func, NULL);
if (iRet)
{
printf("pthread create err\n");
return -1;
}
/* 2. 主线程读取标准输入,发给"接收线程" */
while(1)
{
if(fgets(g_buf, 1000, stdin) != NULL)
{
pthread_mutex_lock(&g_tMutex);
/* 通知接收线程 */
pthread_cond_signal(&g_tConVar);
/* 释放信号量 */
pthread_mutex_unlock(&g_tMutex);
}
}
return 0;
}