线程与信号,线程与锁

#include<stdio.h>
#include<apue.h>
#include<pthread.h>

pthread_mutex_t number_mutex  = PTHREAD_MUTEX_INITIALIZER;
int             globvar  = 0 ;

void *write_p(void *arg){
    while(1){
        pthread_mutex_lock(&number_mutex);
        globvar++;
        printf("the write is %ld\n",globvar);
        pthread_mutex_unlock(&number_mutex);
        sleep(2);

    }
}

void *read_p(void *arg){
    int temp;
    while(1){
        printf("the read is %ld\n",pthread_self());
        pthread_mutex_lock(&number_mutex);
        printf("read = %d\n",globvar);
        sleep(10);
        pthread_mutex_unlock(&number_mutex);

    }
}

int main(){
    pthread_t thid1,thid2;
    int err;
    err = pthread_create(&thid1,NULL,read_p,NULL);
    if(err != 0){
        printf("the pthread is error\n");
    }
    sleep(1);
    printf("the mid \n");
    err = pthread_create(&thid2,NULL,write_p,NULL);
    printf("err is %d\n",err);
    if(err != 0){
        printf("the pthread is error\n");
    }
    while(1){
        sleep(1);
    }
   
#include<stdio.h>
#include<apue.h>
#include<pthread.h>

pthread_mutex_t mutex;
pthread_cond_t    cond ;

void *thread1(void *arg){
    pthread_cleanup_push(pthread_mutex_unlock,&mutex);
    while(1){
        printf("thread1 is runing\n");
        pthread_mutex_lock(&mutex);
        pthread_cond_wait(&cond,&mutex);
        printf("thread applied the condiation\n");
        pthread_mutex_unlock(&mutex);
        sleep(4);
    }
    pthread_cleanup_pop(0);
}

void *thread2(void *arg)
{
    while(1){
        printf("thread2 is runing\n");
        pthread_mutex_lock(&mutex);
        pthread_cond_wait(&cond,&mutex);
        printf("thread2 application is condiation\n");
        pthread_mutex_unlock(&mutex);
        sleep(1);
    }
}

int main(void){

    pthread_t tid1,tid2;
    printf("condiation variable!\n");
    pthread_mutex_init(&mutex,NULL);
    pthread_cond_init(&cond,NULL);
    pthread_create(&tid1,NULL,thread1,NULL);
    pthread_create(&tid2,NULL,thread2,NULL);
    do{
        pthread_cond_signal(&cond);

    }while(1);

    sleep(50);
    pthread_exit(0);

}
#include<stdio.h>
#include<apue.h>
#include<pthread.h>

int quitflag ;             //退出标志
sigset_t mask;             //声明一个信号集

pthread_mutex_t lock = PTHREAD_MUTEX_INITIALIZER;            //初始化一个相互排斥锁
pthread_cond_t waitloc = PTHREAD_COND_INITIALIZER;           //初始化一个条件变量

void * thr_fn(void *arg)                                     //处理信号的线程
{
    int err;
    int signo;
    while(1){
        err = sigwait(&mask,&signo);                         //解除信号屏蔽字
        if(err != 0){
            printf("errpr\n");
        }
        switch(signo){                                      //处理不同的信号
            case SIGINT:                                      //处理SIGINT 信号
                printf("interrupt\n");
                break ;
            case SIGQUIT:                                   //处理SIGQUIT 信号
                pthread_mutex_lock(&lock);                  //上锁
                quitflag = 1;                               //假设不改变这个标志值。不会调出循环
                pthread_mutex_unlock(&lock);                //解锁
                pthread_cond_signal(&waitloc);              //等待条件变量引起唤醒此时堵塞

                printf("case \n");
                return 0;
            default :
                printf("unexpected signal %d\n",signo);
                exit(0);
        }
    }
}

int main()
{
    int err;                                                        //标准错误码
    sigset_t oldmask;                                       //声明原先信号集
    pthread_t tid   ;                                       //声明一个线程号

    sigemptyset(&mask);                                   //清空信号集
    sigaddset(&mask,SIGINT);                                //加入SIGINT 进信号集
    sigaddset(&mask,SIGQUIT);                               //加入SIGQUIT 进信号集

    if((err = pthread_sigmask(SIG_BLOCK,&mask,&oldmask)) != 0) //加入线程信号集主线程開始堵塞这两个信号
        printf("printf SIG_BLOCK is error\n");

    err = pthread_create(&tid,NULL,thr_fn,0);               //创建信号处理线程,新的线程继承了原来的信号屏蔽字
    if(err != 0){
        printf("create is error\n");
    }

    pthread_mutex_lock(&lock);                                   //加锁
    while(quitflag == 0){
        printf("ust \n");
        pthread_cond_wait(&waitloc,&lock);
    }
    pthread_mutex_unlock(&lock);
    printf("like may be\n");
    quitflag = 0;
    printf("change the quitflag\n");
    if(sigprocmask(SIG_SETMASK,&oldmask,NULL) < 0)    //建议完毕工作后将线程屏蔽字还原
        printf("SIG_MASK error");
    exit(0);
}

线程内相互排斥快的原因:

线程的全部资源都在线程空间内。寻址仅仅在本线程内部

进程的消息队列和共享内存会被线程採用==>共享内存最大长处:独立于全部进程

当程序出错时。共享内存会中的数据会保存在内存中。重新启动后会恢复执行状态。

消息队列:独立进程和线程,消息必定会被接收而且会被处理(除非是流水线

作业式)自己能够返回。

接收到消息的线程和进程挨个运行受到消息的处理程序

多任务优势:同一时候执行内核处理——单核分时处理

线程的生命不独立

进程比线程慢的原因:

1)进程空间独立。须要内核作为中转

2)线程在同一进程空间内,寻址内存连续,全部资源在同一进程区间

CUP内核使用率超过100%的原因:

多核处理。每一个CPU的使用率相加则使用率超过100%

线程同步:相互排斥

相互排斥量的种类:

相互排斥量 = 线程锁 = mutex

线程锁,读写锁,自旋锁,条件变量 <==> 线程同步的方式

@线程锁子类:1)普通锁 2)默认锁 3)快速锁 4)错误校验锁 5)回环锁

锁用来异步

int pthread_mutex_lock(pthread_mutex_t *mutex);

int pthread_mutex_trylock(pthread_mutex_t *mutex);

int pthread_mutex_unlock(pthread_mutex_t *mutex);

若已经堵塞的条件下调用pthread_mutex_trylock。则会失败,不能锁住相互排斥量

返回EBUSY。调用该函数防止死锁。

@线程锁堆的初始化

有锁就有线程。锁是为线程准备的。

若不初始化。则锁为上锁状态,无法使用。

int pthread_mutex_destroy(pthread_mutex_t *mutex);

int pthread_mutex_init(pthread_mutex_t *restrict mutex,

const pthread_mutexattr_t *restrict attr);

pthread_mutex_t mutex = PTHREAD_MUTEX_INITIALIZER;

初始化的两种方式:

1)动态:int pthread_mutex_init

2)静态:pthread_mutex_t mutex = PTHREAD_MUTEX_INITIALIZER;

若初始化为默认属性,则attr置值为NULL;

若对静态分配相互排斥量,则把它置为常量PTHREAD_MUTEX_INITIALIZER

@线程锁的使用:先加锁。再使用,再解锁。

@以前拥有锁的人解锁后不sleep的情况下再次拥有锁的机会更大;若解锁后睡眠,

则再次抢到锁的机会就均匀了。

有sleep时,延长了持锁人持锁的时间。本质上是别的线程有了等待的时机。

导致持锁人解锁之后再次持锁的时间变短了。

@10秒内检測是否死锁:

gdb中bt參数查看栈帧,查看方法:

1)查看进程号 a) gdb attach id(进程号)

b) gdb -pid=id(进程号)

2)bt查看栈帧

3)查看进程栈帧局部变量的值

info threads

4)切换进程       thread Id(进程号)

5)查看栈空间     bt full

6)退出进程调试   detach

7)退出gdb        q

@一般说的线程锁是指默认锁,仅仅能加锁一次。回环锁为特殊的线程锁。

能够多次加锁,一般用不到。

@自旋锁的属性

自旋锁:假设自旋锁已经被别的运行单元保持,调用者就一直循环查看是否该

自旋锁的保持已经释放了锁,“自旋”就是循环查看的意思。

@回环锁能够多次加锁,每加一次计数器加一。减锁使用时。每减一次计数器减一

@1)尽量避免多锁穿插使用

2)降低锁的分支

3)线程锁必须在全部函数使用之前声明。相当于全局变量

4)全局变量实现相互排斥,不能代替锁。全局变量不是原子的尽量不要用全局变量

替代锁

@尽可能缩短临界区的长度,避免第二次加锁导致程序被挂起(死锁)

而不能异步相互排斥串行

@加锁的目的就是实现异步相互排斥串行

@不用锁的方法:将资源扩展,使相互排斥的对象变多。

如:10个线程相应10个资源。

信号量、消息队列和共享内存的差别:

@信号量、消息队列是调用系统调用完毕,

@共享内存仅仅是在申请时调用系统调用。之后都在自己的进程区间内

通过指针进行操作。效率比較高。

时间: 2024-12-05 07:53:40

线程与信号,线程与锁的相关文章

12.8 线程和信号

在基于进程模型的信号处理已经比较吗麻烦了,引入线程后事情就更加复杂了. 每个线程拥有其自身的信号掩码,但是信号处理函数是被进程内的所有线程共享的,作为一个推论,独立的线程能够阻塞信号,但是如果一个线程修改与给定信号的处理动作的时候,所有的线程都会共享这一修改.也就是说,如果一个线程选择忽略一个给定信号,其他的线程可能会通过恢复默认呢处理或者是安装信号处理函数的方式撤销线程所做的忽略选择. 信号会只会被发送到进程内的一个线程.如果信号与硬件错误相关,那么信号通常被发送到造成时间发生的线程,其他信号

线程同步机制之互斥锁

进程间通讯介绍 1.几种进程间的通信方式 # 管道( pipe ):管道是一种半双工的通信方式,数据只能单向流动,而且只能在具有亲缘关系的进程间使用.进程的亲缘关系通常是指父子进程关系. # 有名管道 (named pipe) : 有名管道也是半双工的通信方式,但是它允许无亲缘关系进程间的通信. # 信号量( semophore ) : 信号量是一个计数器,可以用来控制多个进程对共享资源的访问.它常作为一种锁机制,防止某进程正在访问共享资源时,其他进程也访问该资源.因此,主要作为进程间以及同一进

C++线程中的几种锁

线程之间的锁有:互斥锁.条件锁.自旋锁.读写锁.递归锁.一般而言,锁的功能越强大,性能就会越低. 1.互斥锁 互斥锁用于控制多个线程对他们之间共享资源互斥访问的一个信号量.也就是说是为了避免多个线程在某一时刻同时操作一个共享资源.例如线程池中的有多个空闲线程和一个任务队列.任何是一个线程都要使用互斥锁互斥访问任务队列,以避免多个线程同时访问任务队列以发生错乱. 在某一时刻,只有一个线程可以获取互斥锁,在释放互斥锁之前其他线程都不能获取该互斥锁.如果其他线程想要获取这个互斥锁,那么这个线程只能以阻

线程同步机制之互斥锁通信机制

#include <stdio.h> #include <stdlib.h> #include <pthread.h> #include <string.h> void *thread_function(void *arg); pthread_mutex_t work_mutex; #define WORK_SIZE 1024 char work_area[WORK_SIZE]; int time_to_exit=0; int main(int argc,

第9章 线程编程(4)_线程同步1:互斥锁

5. 线程的互斥和同步 5.1 同步和互斥的概念 (1)线程同步:是一个宏观概念,在微观上包含线程的相互排斥和线程的先后执行的约束问题.解决同步方式一般采用条件变量和信号量. (2)线程互斥:线程执行的相互排斥(注意,它不关心线程间执行的先后顺序!).解决互斥一般使用互斥锁.读写锁和信号量. [编程实验]银行ATM(线程不安全的例子) //account.h #ifndef __ACCOUNT_H__ #define __ACCOUNT_H__ typedef struct { int code

多个写线程一个读线程的无锁队列实现

在之前的一篇博客中,写了一个在特殊情况下,也就是只有一个读线程和一个写线程的情况下,的无锁队列的实现.其中甚至都没有利用特殊的原子加减操作,只是普通的运算.这样做的原因是,即使是特殊的原子加减操作,也比普通的加减运算复杂度高很多.因此文中的实现方法可以达到很高的运行效率. 但是,有的情况下并不是只有一个读线程和一个写线程.越是一般化的实现,支持的情况越多,但是往往损失的性能也越多.作者看到过一个实现(http://www.oschina.net/code/snippet_732357_13465

线程同步:何时互斥锁不够,还需要条件变量?

http://www.blogjava.net/fhtdy2004/archive/2009/07/05/285519.html 线程同步:何时互斥锁不够,还需要条件变量? 很显然,pthread中的条件变量与Java中的wait,notify类似 假设有共享的资源sum,与之相关联的mutex 是lock_s.假设每个线程对sum的操作很简单的,与sum的状态无关,比如只是sum++.那么只用mutex足够了.程序员只要确保每个线程操作前,取得lock,然后sum++,再unlock即可.每个

线程的信号机制

摘自:http://www.cnblogs.com/willick/p/4177977.html  仅供参考学习 有时候你需要一个线程在接收到某个信号时,才开始执行,否则处于等待状态,这是一种基于信号的事件机制..NET框架提供一个ManualResetEvent类来处理这类事件,它的 WaiOne 实例方法可使当前线程一直处于等待状态,直到接收到某个信号.它的Set方法用于打开发送信号.下面是一个信号机制的使用示例: 1 //线程的信号机制 2 #region 3 var signal = n

线程与进程--线程三把锁

为什么要有三把锁 学习三把锁时候我们需要先知道为什么要有三把锁 全局资源(counter)被抢占的情况,问题产生的原因就是没有控制多个线程对同一资源的访问,对数据造成破坏,使得线程运行的结果不可预期.这种现象称为"线程不安全".在开发过程中我们必须要避免这种情况,那怎么避免?这就用到了我们在综述中提到的互斥锁了. 同步锁 (Lock)又名互斥锁 互斥锁概念 Python编程中,引入了对象互斥锁的概念,来保证共享数据操作的完整性.每个对象都对应于一个可称为" 互斥锁"

Qt跨线程发送信号与元数据

转载请注明出处:http://blog.csdn.net/luotuo44/article/details/39395025 Qt的signals/slots是可以用在线程间的.由于事件循环(event loop)是在主线程完成的,所以在非主线程发送一个信号时,对应的槽函数将会由主线程执行. 熟悉多线程的读者应该都感受到这里会有一个微妙的问题.如果signals/slots的函数参数是一个自己定义的类型.比如自己定义了一个Student类,信号函数为sendStudent(const Stude