pthread多线程基础知识学习
定义
POSIX线程(POSIX threads),简称Pthreads,是线程的POSIX标准。该标准定义了创建和操纵线程的一整套API。在类Unix操作系统(Unix、Linux、Mac OS X等)中,都使用Pthreads作为操作系统的线程。Windows操作系统也有其移植版[pthreads-win32][6]。
数据类型
- pthread_t:线程ID
- pthread_attr_t:线程属性
常用函数
- pthread_create
int pthread_create(pthread_t tidp,const pthread_attr_t *attr,(void)(start_rtn)(void),void *arg);
第一个参数是进程的名字,指针变量,第二个属性设置,NULL,没有属性,第三个是线程运行的起始地址,注意格式,最后一个是运行函数的参数。 - pthread_join()
阻塞当前的线程,直到另外一个线程运行结束
工具函数
pthread_equal(): 对两个线程的线程标识号进行比较
pthread_detach(): 分离线程
pthread_self(): 查询线程自身线程标识
**补充知识** void *() &void* ()void*()区别
他们三者根本没有区别,void指的是返回值为空,void * 指的是返回值是任何类型的指针。
例子:注意编译加上**-lpthead**
#include <stdio.h>
#include <stdlib.h>
#include <pthread.h>
#include <unistd.h>
#include <string.h>
void printids(const char *s)
{
pid_t pid; // int
pthread_t tid;
pid = getpid(); //for the id of process
tid = pthread_self();//查询线程自身线程标识号
printf("%s pid %u tid %u (0x%x)\n", s, (unsigned int) pid,
(unsigned int) tid, (unsigned int) tid);
}
void *thr_fn(void *arg)
{
printids("new thread: ");
return NULL;
}
int main(void)
{
int err;
pthread_t ntid;
err = pthread_create(&ntid, NULL, thr_fn, NULL);// 注意线程的入口在的地方。
if (err != 0)
printf("can't create thread: %s\n", strerror(err));
printids("main thread:");
pthread_join(ntid,NULL);
}
其他操纵函数
pthread_create():创建一个线程
pthread_exit():终止当前线程
pthread_cancel():中断另外一个线程的运行
pthread_join()
int pthread_join(pthread_t thread, void **retval);
阻塞当前的线程,直到另外一个线程运行结束
retval: 用户定义的指针,用来存储被等待线程的返回值,NUll不用进行储存状态。
pthread_attr_init():初始化线程的属性
pthread_attr_setdetachstate():设置脱离状态的属性(决定这个线程在终止时是否可以被结合)
pthread_attr_getdetachstate():获取脱离状态的属性
pthread_attr_destroy():删除线程的属性
pthread_kill():向线程发送一个信号
int pthread_kill(pthread_t thread, int sig)。
#include<stdio.h>
#include<unistd.h>
#include<signal.h>
#include<pthread.h>
#include<time.h>
pthread_t tid;
sigset_t set;
void myfunc()
{
printf("hello\n");
}
static void *mythread(void*p)//注意格式用来做create的入口指针
{
int signum;
while(1)
{
sigwait(&set,&signum);
if(SIGUSR1==signum)
myfunc();
if(SIGUSR2==signum)
{
printf("Iwillsleep2secondandexit\n");
sleep(2);
break;
}
}
}
int main()
{
char tmp;
void *status;
sigemptyset(&set);
sigaddset(&set,SIGUSR1);
sigaddset(&set,SIGUSR2);
sigprocmask(SIG_SETMASK,&set,NULL);
pthread_create(&tid,NULL,mythread,NULL);
while(1)
{
printf(":");
scanf("%c",&tmp);
if('a'==tmp)
{
pthread_kill(tid,SIGUSR1);//发送SIGUSR1,打印字符串。
}
else if('q'==tmp)
{
//发出SIGUSR2信号,让线程退出,如果发送SIGKILL,线程将直接退出。
pthread_kill(tid,SIGUSR2);
//等待线程tid执行完毕,这里阻塞。
pthread_join(tid,&status);
printf("finish\n");
break;
}
else
continue;
}
return 0;
}
调试问题总结
1,expected identifier before numeric constant
解决方式:原来是因为有其他模块定义了同名的的变量。太恶心了,报的错和实际的问题完全没有提示。
2error: name lookup of ‘j’ changed for ISO ‘for’ scoping [-fpermissive]
错误的原因: for循环中在初始化时同时定义的变量的作用域范围的一个问题。
ISO/ANSI C++ 把在此定义的变量的作用域范围限定在 for 循环体内,也就是说,在循环体之外这个变量是无效的。但是编译的时候可以加参数-fpermissive,就没有问题了。如果不加这个参数,直接把for中定义并初始化的变量,定义与初始化分离:
2 in C++98 ‘box1’ must be initialized by constructor, not by ‘{…}’请问这是什么意思?怎么改?
变量初始化的时候,需要使用括号(),或者还有另外一种方式就是通过使用codeblocks中的编译选项,添加c11即可。
线程互斥锁的学习
目的:为了保持线程之间的同步。
常用函数:phread_mutex_init,pthread_mutex_destroy,phtread_mutex_lock,pthread_mutex_unlock.分别对应锁的初始化,销毁,锁定和解锁的目标。
如何创建锁呢?
答案就是需要初始化。两种方式,第一,静态方式。使用宏PTHREAD_MUTEXZ_INITIALIZATION,互斥所是一个pthread_mutex_t的结构体,而这个宏定义是一个结构常量。第二种方式呢?就是通过pthread_mutex_t的结构体,
int pthread_mutex_init(pthread_mutex_t *mutex, const pthread_mutexattr_t * attr)。
锁的类型
*PTHREAD_MUTEX_TIMED_NP*,这是缺省值,也就是普通锁。当一个线程加锁以后,其余请求锁的线程将形成一个等待队列,并在解锁后按优先级获得锁。这种锁策略保证了资源分配的公平性。
PTHREAD_MUTEX_ERRORCHECK_NP,检错锁,如果同一个线程请求同一个锁,则返回EDEADLK,否则与PTHREAD_MUTEX_TIMED_NP类型动作相同。这样就保证当不允许多次加锁时不会出现最简单情况下的死锁。
PTHREAD_MUTEX_ADAPTIVE_NP,适应锁,动作最简单的锁类型,仅等待解锁后重新竞争。
可以用
pthread_mutexattr_settype(pthread_mutexattr_t *attr , int type)
pthread_mutexattr_gettype(pthread_mutexattr_t *attr , int *type)
获取或设置锁的类型。
锁的释放
调用pthread_mutex_destory之后,可以释放锁占用的资源,但这有一个前提上锁当前是没有被锁的状态。
锁操作
对锁的操作主要包括加锁 pthread_mutex_lock()、解锁pthread_mutex_unlock()和测试加锁 pthread_mutex_trylock()三个。
int pthread_mutex_lock(pthread_mutex_t *mutex)
int pthread_mutex_unlock(pthread_mutex_t *mutex)
int pthread_mutex_trylock(pthread_mutex_t *mutex)
pthread_mutex_trylock()语义与pthread_mutex_lock()类似,不同的是在锁已经被占据时返回EBUSY而不是挂起等待
关于socket的几点说明: