线程创建原因
在多线程应用程序中,当多个线程共享相同的内存时,如同时访问一个变量时,需要确保每个线程看到一致的数据视图,即保证所有线程对数据的修改是一致的。
一个典型的例子是,在一个多线程程序中,两个及以上个线程对同一个变量i执行i++操作,结果得到的值并不如顺序执行所预期的那样。这就是线程间不同步的一个例子。
== 每个线程使用的变量都是其他线程不会读取和修改的
变量是只读的== 则可以不用加锁
==发现如果把pthread_mutex_unlock放在usleep()函数后面的话,其他4个线程就一直阻塞在lock上.
查了下资料,原来当这个线程从usleep()醒来后,unlock掉mutex之后,线程调度程序并不会立即让其他线程去占有这个mutex,由于当前线程刚从还有剩余时间片,于是又得到了这个mutex,而其他的线程就没有机会得到这个mutex.
解决方法就是把usleep(500000)和pthread_unlock_mutex(&conn_mutex)换个位置
结论:不要持有一个mutex太久,特别是不能在sleep()的时候持有一个mutex ==
流程如下
1:锁初始化;
static pthread_mutex_t mutex;
pthread_mutex_init(&mutex, NULL);
2:初始化条件变量:为了避免死锁的发生;
pthread_cond_init(&cond, NULL);//初始化一条件变量:是给线程共用的,防止锁死(进入某个线程,发现条件不成立,出不来)。
3:设置调度参数
setup_sched_parameters(&tattr, 99); //设置调度参数 包括设置 inheritsched(继承性) 和pthread_attr_setschedpolicy(线程策略)
pthread_attr_setinheritsched(attr, PTHREAD_EXPLICIT_SCHED) 这个函数有2个参数
attr :表示线程属性。
另一个参数有2种 :
PTHREAD_EXPLICIT_SCHED,线程能继承自己设置优先级和调度策略有效
PTHREAD_INHERIT_SCHED, 新的线程继承创建线程的策略和参数!
ret = pthread_attr_setschedpolicy(attr, prio ? SCHED_FIFO : SCHED_OTHER);
设置线程优先级和调度参数,如果成功返回,则支持SCHED_FIFO(先进先出),否则SCHED_FIFO(其他方法)
/* SCHED_OTHER是不支持优先级使用的, 而SCHED_FIFO和SCHED_RR 支持优先级的使用, 他们分别为1和99, 数值越大优先级越高.
注意:
> 此处的SCHED_FIFO是允许被高优先级抢占的!
> 也就是有高优先级的必须先运行
> SCHED_RR是设置一个时间片
> 当有SCHED_FIFO或SCHED_RR策赂的线程在一个条件变量上等持或等持加锁同一个互斥量时,它们将以优先级顺序被唤醒。即,如果一个低优先级的SCHED_FIFO线程和一个高优先织的SCHED_FIFO线程都在等待锁相同的互斥且,则当互斥量被解锁时,高优先级线程将总是被首先解除阻塞。*/
4: 创建线程
ret = pthread_create(&pth_task0, &tattr, test_thread, NULL);//创建线程1,函数处理test_thread
5:去除初始化
函数将对象属性初始化为其缺省值。分配一些存储空间,所以需要下面的函数删除初始化期间分配的存储空间。
属性对象被销毁,并不影响线程的属性。
pthread_attr_destroy(&tattr);
加锁很详细
#include <iostream>
#include <pthread.h>
#include <signal.h>
#include <windows.h>
//#pragma comment(lib,"x64/pthreadVC2.lib")
using namespace std;
static int condition = 0; //所谓的全局变量,有线程进入的条件
static int value = 0;
static pthread_mutex_t mutex;
static pthread_cond_t cond;
pthread_attr_t tattr;//线程1属性对象
// pthread_attr_t//主要包括scope属性、detach属性、堆栈地址、堆栈大小、优先级。在pthread_create中,把第二个参数设置为NULL的话,将采用默认的属性配置。
pthread_attr_t tattr1;//线程2属性对象
pthread_t pth_task0; //pthread_t声明线程ID
pthread_t pth_task1;
static void signal_handler(int sig)
{
exit(0);
}
static void setup_sched_parameters(pthread_attr_t *attr, int prio)
{
struct sched_param p; //描述调度参数的结构概要
int ret;
ret = pthread_attr_init(attr); //线程初始化
if (ret)
{
//error(1, ret, "pthread_attr_init()");
}
ret = pthread_attr_setinheritsched(attr, PTHREAD_EXPLICIT_SCHED); //必须先设置inheritsached 为PTHREAD_EXPLICIT_SCHED,线程才能继承自己设置优先级和调度策略有效
//另外一个参数PTHREAD_INHERIT_SCHED, 新的线程继承创建线程的策略和参数!
if (ret)
{
//error(1, ret, "pthread_attr_setinheritsched()");
}
ret = pthread_attr_setschedpolicy(attr, prio ? SCHED_FIFO : SCHED_OTHER); // 设置线程优先级和调度参数,如果成功返回,则支持SCHED_FIFO(先进先出),否则SCHED_FIFO(其他方法)
/*SCHED_OTHER是不支持优先级使用的, 而SCHED_FIFO和SCHED_RR
支持优先级的使用, 他们分别为1和99, 数值越大优先级越高.
注意:
> 此处的SCHED_FIFO是允许被高优先级抢占的!
> 也就是有高优先级的必须先运行
> SCHED_RR是设置一个时间片
> 当有SCHED_FIFO或SCHED_RR策赂的线程在一个条件变量
上等持或等持加锁同一个互斥量时,它们将以优先级顺序被唤
醒。即,如果一个低优先级的SCHED_FIFO线程和一个高优先
织的SCHED_FIFO线程都在等待锁相同的互斥且,则当互斥量
被解锁时,高优先级线程将总是被首先解除阻塞。*/
if (ret)
{
//error(1, ret, "pthread_attr_setschedpolicy()");
}
/* Set scheduling priority 设置调度优先级*/
p.sched_priority = prio;
ret = pthread_attr_setschedparam(attr, &p); //用来设置线程的调度参数
// 前提条件是这个参数仅当调度策略为实时(即SCHED_RR或SCHED_FIFO)时才有效,并可以在运行时通过pthread_setschedparam()函数来改变,缺省为 0 。
if (ret)
{
//error(1, ret, "pthread_attr_setschedparam()");
}
}
static void* test_thread(void* arg)
{
while (1)
{
/*上锁*/
pthread_mutex_lock(&mutex);
while (condition <= 0)
{
/*条件不满足,等待条件,释放互斥锁*/
//printf("wait condition %lx\n", (long)pthread_self());
pthread_cond_wait(&cond, &mutex);
}
//printf("get lock thred Id %lx\n", (long)pthread_self());
//sleep(5);
condition--;
//printf("unlock thred Id %lx, value:%d, condition:%d\n",
//(long)pthread_self(),
// ++value,
// condition);
/*解锁退出*/
pthread_mutex_unlock(&mutex);
Sleep(1);
cout << "线程2" << endl;
}
}
static void* test2_thread(void* arg)
{
while (1)
{
/*上锁*/
pthread_mutex_lock(&mutex);
while (condition <= 0)
{
/*条件不满足,等待条件*/
//printf("wait condition %lx\n", (long)pthread_self());
pthread_cond_wait(&cond, &mutex);
}
//printf("get lock thred Id %lx\n", (long)pthread_self());
//sleep(5);
condition--;
//printf("unlock thred Id %lx, value:%d, condition:%d\n",
//(long)pthread_self(),
// ++value,
// condition);
/*解锁退出*/
pthread_mutex_unlock(&mutex);
Sleep(1);
cout << "线程3" << endl;
}
}
int main(int argc, char** argv)
{
/*main函数功能:第一步:设置好锁和线程参数并创建线程
第二步:main函数主线程来解锁哪个线程,实现同步处理
*/
int ret = -1;
signal(SIGTERM, signal_handler); //请求中止进程,kill命令缺省发送
signal(SIGINT, signal_handler); //由Interrupt Key产生,通常是CTRL+C或者DELETE。发送给所有ForeGround Group的进程??不太懂
pthread_mutex_init(&mutex, NULL); //锁初始化
pthread_cond_init(&cond, NULL);//初始化一条件变量:是给线程共用的,防止锁死(进入某个线程,发现条件不成立,出不来)。
setup_sched_parameters(&tattr, 99); //设置调度参数 包括设置inheritsched 和pthread_attr_setschedpolicy
ret = pthread_create(&pth_task0, &tattr, test_thread, NULL);//创建线程1,函数处理test_thread
if (ret)
{
//printf("create thread:%s\n", strerror(ret));
cout << "线程11" << ret << endl;
return -1;
}
pthread_attr_destroy(&tattr);
setup_sched_parameters(&tattr1, 99);
ret = pthread_create(&pth_task1, &tattr1, test2_thread, NULL);
if (ret)
{
//printf("create thread:%s\n", strerror(ret));
cout << "线程22" << ret << endl;
return -1;
}
pthread_attr_destroy(&tattr1);
while (1)
{
Sleep(5); //sleep作用,为了暂缓一段时间在使用,防止cpu占用过高。
/* 主线程获取锁 */
pthread_mutex_lock(&mutex);
printf("main thread locked\n");
condition++;
//printf("add condition thread id %lx\n", (long)pthread_self());
/* 主线程解锁 */
printf("main thread unlocked\n");
pthread_mutex_unlock(&mutex);
/* 主线程唤醒在条件上等待的线程 */
pthread_cond_signal(&cond);
/* 主线程唤醒所有等待线程 */
// pthread_cond_broadcast(&cond);
}
pthread_join(pth_task0, NULL);
pthread_join(pth_task1, NULL);
return 0;
}
不加锁此时注意不要在多线程内加全局变量
#include <iostream>
#include <pthread.h>
#include <signal.h>
#include <windows.h>
//#pragma comment(lib,"x64/pthreadVC2.lib")
using namespace std;
#define NUM_THREADS 2 //线程数
void* say_hello(void* args)
{
cout << "hello..." << endl;
return 0;
} //函数返回的是函数指针,便于后面作为参数
void* say_goodbye(void* args)
{
cout << "good bye" << endl;
return 0;
}
int main() {
cout << "babb" << endl;
pthread_t tids[NUM_THREADS]; //线程id 数组
for (int i = 0; i < NUM_THREADS; ++i)
{
int ret = pthread_create(&tids[0], NULL, say_hello, NULL); //参数:创建的线程id,线程参数,线程运行函数的起始地址,运行函数的参数
if (ret != 0) //创建线程成功返回0
{
cout << "pthread_create error:error_code=" << ret << endl;
}
int ret_2 = pthread_create(&tids[1],NULL,say_goodbye,NULL);
if (ret_2 != 0)
{
cout << "pthread_create error:error_code=" << ret_2 << endl;
}
}
pthread_exit(NULL); //等待各个线程退出后,进程才结束,否则进程强制结束,线程处于未终止的状态
system("pause");
return 0;
}