Posix线程
#include <pthread.h>
int pthread_create(&tid, &attr, func, args); //线程ID, 属性(优先级,守护线程), 函数,参数
(void *)(* func)(void *) // void *可以传任何参数,返回任何值
0: 成功 错误时不设置errno, 返回正值Exxx, EAGAIN。。。
int pthread_join(tid, &pState)
// 等待线程tid结束,并将状态返回(二级指针)。0:成功,同上
// 不像进程可以等待任意子进程结束
pthread_t pthread_self()
// 线程tid为无符号整数
int pthread_detach(tid)
//可汇合的线程,结束时保留状态;分离的线程,结束时资源全部释放
//被想脱离自己的线程调用。
void pthread_exit(&status)
//线程终止
互斥锁:
阻止对共享变量的同时访问 // 545/873 pthread_mutex_t (mutual exclusion)
pthread_mutex_t lock = PTHREAD_MUTEX_INITIALIZER
pthread_mutex_init //用共享内存分配的锁,用此函数初始化
pthread_mutex_lock(&lock);
local_var = g_counter; // A : 两个线程都操作这3行,某个线程在A或者B点,切换到另一个线程去一直执行,
printf("%d: %d", tid, local_var + 1); // B : 再切换回来,A的local_var还是原来的值,加1后覆盖g_counter,出现错误!
g_counter = local_var + 1;
pthread_mutex_unlock(&lock)
条件变量:
睡眠等待某种条件出现 // 549/873 pthread_cond_t
int pthread_cond_wait(*condi, *mutex) // A线程在等待条件M
int pthread_cond_signal(*condi) // B线程通知一个等待条件M的线程
int pthread_cond_timedwait(条件,锁,绝对时间)
int pthread_cond_broadcast(*condi) // 通知所有
线程与进程的区别
进程fork的问题:
1. 昂贵。虽然用了写时拷贝技术,但内存映像,描述字要拷贝到子进程。
2. 通信。父子进程通信不方便,虽然有IPC通信。
线程:
1. 创建一般快10-100倍
2. 进程内的线程共享资源(进程指令,打开的文件,信号处理,工作目录,用户ID和组ID),除了ID,寄存器,栈,信号掩码,优先级,errno
3. 引入了同步问题。 func_r 为线程安全的函数,即无全局或者静态变量(线程共享不安全)。
4. 线程函数的参数为 void *, 将int 转成它,只有在整数大小 <= 指针大小 的系统上该强转才工作。
若 &connId, 则因为线程间共享,所以不安全。
若 pConnId, 每个线程新分配一个,但malloc , free , 是不可重入的函数(有静态变量)。
区别: 总之:线程共享,进程复制
在用子进程或者线程处理服务器监听收到客户端请求,即accept后的处理
父进程需要关闭accept的连接;线程不能关(共享,关了后,生成的线程无法处理)
生成线程中处理完后关闭客户端的连接;子进程不必关(子进程结束后,其连接自动关了)
例子:
pthread_cond_wait(&products->notFull, &products->locker); // 等
pthread_cond_signal(&products->notFull); // 通知
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <pthread.h>
#define BUFFER_SIZE 8
#define END_FLAG (-1)
struct Products
{
int buffer[BUFFER_SIZE];
pthread_mutex_t locker; //保证存取操作的原子性 互斥性
pthread_cond_t notEmpty; //是否可读
pthread_cond_t notFull; //是否可写
int posReadFrom;
int posWriteTo;
};
int BufferIsFull(struct Products* products)
{
if ((products->posWriteTo + 1) % BUFFER_SIZE == products->posReadFrom)
{
return (1);
}
return (0);
}
int BufferIsEmpty(struct Products* products)
{
if (products->posWriteTo == products->posReadFrom)
{
return (1);
}
return (0);
}
//制造产品。
void Produce(struct Products* products, int item)
{
pthread_mutex_lock(&products->locker);
//无空间可写入
while (BufferIsFull(products))
{
pthread_cond_wait(&products->notFull, &products->locker);
}
//写入数据
products->buffer[products->posWriteTo] = item;
products->posWriteTo++;
if (products->posWriteTo >= BUFFER_SIZE)
products->posWriteTo = 0;
// 通知不空,可读了
pthread_cond_signal(&products->notEmpty);
//解锁
pthread_mutex_unlock(&products->locker);
}
int Consume(struct Products* products)
{
int item;
pthread_mutex_lock(&products->locker);
while (BufferIsEmpty(products))
{
pthread_cond_wait(&products->notEmpty, &products->locker);
} //为空时持续等待,无数据可读
//提取数据
item = products->buffer[products->posReadFrom];
products->posReadFrom++;
if (products->posReadFrom >= BUFFER_SIZE) //如果到末尾,从头读取
products->posReadFrom = 0;
pthread_cond_signal(&products->notFull);
pthread_mutex_unlock(&products->locker);
return item;
}
struct Products products;
void* ProducerThread(void* data)
{
int i;
for (i = 0; i < 16; ++i)
{
printf("producer: %d\n", i);
Produce(&products, i);
}
Produce(&products, END_FLAG);
return NULL;
}
void* ConsumerThread(void* data)
{
int item;
while (1)
{
item = Consume(&products);
if (END_FLAG == item)
break;
printf("consumer: %d\n", item);
}
return (NULL);
}
int main(int argc, char* argv[])
{
pthread_t producer;
pthread_t consumer;
int result;
pthread_create(&producer, NULL, &ProducerThread, NULL);
pthread_create(&consumer, NULL, &ConsumerThread, NULL);
pthread_join(producer, (void *)&result);
pthread_join(consumer, (void *)&result);
exit(EXIT_SUCCESS);
}