linux的互斥量:是指通过在系统的临界区进行锁定这个区域也就是获取临界区资源 还有释放资源 其实就是加锁和释放锁
linux的信号量:一般是指一个信号灯 比如我有一个车库那么 我进来一量车 那么就一个信号灯进行加一 如果走出去那么就进行减一 当加一的时候 其他的车无法进来 这里我设的是一个信号灯 当我通过sem_init函数进行设置多个信号灯的时候 那么就是限制多个位置 当有了车就其他车不能占用这个位置 可以用在线程 其实也就相当于一种锁的形式了 多数使用 这几个函数
创建 sem_init
等待 sem _wait
释放 sem _post
销毁 sem_destroy
不过我使用信号量的时候 定义sem_t 一个信号 然后先进行sem_unlink 删除系统已经创建好的信号 在/dev/shm文夹下面的信号 不过他删除的是有名信号量 因为不删除的话他会一直存在 占用空间 而且信号量是共享内存空间的 而且一定要在sem_close关闭信号量之后才可以进行删除 然后我进行sem_open 创建有名信号量 然后赋值给sem_val 引用计 然后进行sem_post 和sem_wait 进行操控信号量的sem_val 这个过程相当于互斥锁
注意事项:
每个信号量有一个引用计数器记录打开的次数,当引用计数大于0时,name 就能从文件系统中删除,然而其信号量的析构(不同于将他的名字从文件系统中删除)却要等到最后一个sem_close发生时为止.
举个例子
int makeSem(sem_t **sem)
{
sem_unlink( OPEN_SESAME );//从内核中删除有名信号量 但是他的最终删除操作一定要等到
//最后的sem_close()
//信号量名 创建信号量(当打开一个不存在的信号量时设置0)
//模式 可读可写 普通文件
//SEM—Value 值
if((*sem = sem_open( OPEN_SESAME, O_CREAT, 0666 | S_IRUSR | S_IWUSR, 0)) == SEM_FAILED)
{
perror(“failed to create semaphore”);
return 0;
}
return 1;
}
互斥信号量:
首先定义pthread_mutex_t mutex;
然后int pthread_mutex_init(pthread_mutex_t *mutex, const pthread_mutexattr_t * attr) 创建信号互斥锁 第二个参数是属性互斥锁所属的属性
以下是互斥锁属性:
PTHREAD_MUTEX_TIMED_NP,这是缺省值,也就是普通锁。当一个线程加锁以后,其余请求锁的线程将形成一个等待队列,并在解锁后按优先级获得锁。这种锁策略保证了资源分配的公平性。
PTHREAD_MUTEX_RECURSIVE_NP,嵌套锁,允许同一个线程对同一个锁成功获得多次,并通过多次unlock解锁。如果是不同线程请求,则在加锁线程解锁时重新竞争。
PTHREAD_MUTEX_ERRORCHECK_NP,检错锁,如果同一个线程请求同一个锁,则返回EDEADLK,否则与PTHREAD_MUTEX_TIMED_NP类型动作相同。这样就保证当不允许多次加锁时不会出现最简单情况下的死锁。
接着是:
pthread_mutex_lock 锁定临界资源 通过这个锁
pthread_mutex_unlock 释放这个临界资源 其实释放当前占用这个线程的锁
pthread_mutex_destroy銷毀這個锁
互斥锁的范围:可以指定是该进程与其他进程的同步还是同一进程内不同的线程之间的同步。可以设置为PTHREAD_PROCESS_SHARE和PTHREAD_PROCESS_PRIVATE。默认是后者,表示进程内使用锁。可以使用int pthread_mutexattr_setpshared(pthread_mutexattr_t *mattr, int pshared)
不过这个貌似很少用 所以新手不需要考虑
其实在我看来 不管是信号量还是互斥量 实际使用的时候 其实都差不多了 不需要考虑那么多 一般使用这两个量是用在异步上面
不过前者的话是用在同步上面 多个线程同时访问一个资源 但是是有序的 这个有序是指 一个一个的来 但是在处理每个线程的情况下是互斥的 就是线程的回调函数是互斥的 一哥线程执行完另一个才可以进行执行 其实本质上都差不多了 只不过后者 只用在线程回调函数的处理模块上 而信号量的话可以同时让多个回调函数去拥有各自的位置 而且一次性给这些线程cpu资源 但是处理是有序的一个一个来 这个也是可以有效的防止死锁的产生的
死锁:死鎖是指 比如A和B 线程1占用了A的资源等待B的资源 但是线程2占用了B的资源 等待线程A的资源 两者就互相阻塞了
还有一种就是A->B->C->A 这样的圆环状 A等待B B等C C等A 这样处于僵持状态 所以叫做死锁
//线程的使用函数 一般都会使用这几种函数进行 不过我喜欢添加
#include<pthread.h>
函数定义: int pthread_join(pthread_t thread, void **retval);
描述 :pthread_join()函数,以阻塞的方式等待thread指定的线程结束。当函数返回时,被等待线程的资源被收回。如果线程已经结束,那么该函数会立即返回。并且thread指定的线程必须是joinable的。
参数 :thread: 线程标识符,即线程ID,标识唯一线程。retval: 用户定义的指针,用来存储被等待线程的返回值。
返回值 : 0代表成功。 失败,返回的则是错误号。
pthread_create 创建线程 pthread_t 是线程id pthread_exit 退出线程 pthread_cancel 取消线程传入线程id
pthread_detach 分离线程 如果正常的情况下 我们会使用pthread_join 去等待线程结束 然后释放线程占用资源 但是如果在服务器 我们不希望一个客户接入的时候 我们服务器进程就一直等待一个线程结束 所以呢 我们会使用pthread_detach去分离这个线程让这个线程自动运行完毕的时候进行释放资源 pthread_detach(pthread_self());