• Linux 进程与线程四(加锁--解锁)


    线程共享进程的内存空间,打开的文件描述符,全局变量。
    当有多个线程同事访问一块内存空间或者一个变量、一个文件描述符,如果不加控制,那么可能会出现意想不到的结果。
    原子操作
    对于我们的高级语言(C语言,java,c#),普通的一句代码一般都是由多条汇编语句组成,计算机CPU每次所执行的都是一条汇编指令
    ,一条汇编指令是无法再次拆分的,所以计算机CPU同一时间只能执行一条汇编指令就是一个原子操作。
    互斥(mutex)是相互排斥的意思,它是一种锁或者信号灯。
    互斥用来保护多个线程共享的数据和结构不会被同事修改,一个互斥锁只能有两个状态
    --locked    加锁
    --unlocked    解锁
    加锁后互斥不让其他线程访问。
    任何时刻只能有一个线程来掌握某个互斥上锁。
    锁操作是一个原子操作
    一个线程如果试图在一个已经加锁的互斥上再加锁,这个线程会被挂起,,直到加锁的线程释放掉互斥锁为止。
    强调:加锁解锁针对的是pthread_mutex_t类型的变量,只要有一个地方加锁,哪怕在别的线程中有加锁代码,那个线程也会被挂起,
    只有当pthread_mutex_t类型的变量解锁后,其他的线程才可以继续对pthread_mutex_t类型的变量加锁。 注意:互斥情况下,如果将某个正在加锁占用资源的进程用pthread_cancel函数取消掉,可能产生死锁。

    pthread_mutex_t mutex=PTHREAD_MUTEX_INITIALIZER;
    int pthread_mutex_lock(pthread_mutex_t *mutex);
    int pthread_mutex_unlock(pthread_mutex_t *mutex);
    PTHREAD_MUTEX_INITIALIZER是初始化一个快速锁的宏定义。
    pthread_mutex_lock用户给mutex加锁。
    pthread_mutex_unlock用于给mutex解锁

    //线程加锁--pthread_mutex_lock
    #include <stdio.h>
    #include <stdlib.h>
    #include <string.h>
    
    #include <unistd.h>
    #include <errno.h>
    #include <pthread.h>
    
    //定义一个全局的互斥变量
    pthread_mutex_t mutex = PTHREAD_MUTEX_INITIALIZER;
    int count = 0;
    
    void * MyFunc(void * arg)
    {
        if (arg == NULL)
        {
            printf("param is not allow NULL!
    ");
            return NULL;
        }
        //加锁--所有线程都能访问的全局变量加锁
        pthread_mutex_lock(&mutex);
        int * pnumx = (int *) arg;
        int i = 0;
        while (i < 10)
        {
            printf("thread%d count=%d
    ", *pnumx, count++);
            sleep(1);
            i++;
        }
        //解锁
        pthread_mutex_unlock(&mutex);
        return NULL;
    }
    
    void * MyFunc2(void * arg)
    {
        if (arg == NULL)
        {
            printf("param is not allow NULL!
    ");
            return NULL;
        }
        //这个锁和myfunc中的锁是同一个锁,myfunc被锁,这里也会被锁
        pthread_mutex_lock(&mutex);
        int * pnumx = (int *) arg;
        int i = 0;
        while (i < 10)
        {
            printf("thread%d count=%d
    ", *pnumx, count++);
            sleep(1);
            i++;
        }
        //解锁
        pthread_mutex_unlock(&mutex);
        return NULL;
    }
    
    int main(int arg, char * args[])
    {
        pthread_t thr1, thr2;
        pthread_attr_t attr;
        pthread_attr_init(&attr);
        //设置进程为可分离状态
        pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED);
        int a = 1, b = 2;
        //创建线程
        if (pthread_create(&thr1, &attr, MyFunc, &a) != 0)
        {
            printf("create thread is failed ! error message :%s
    ",
                    strerror(errno));
            return -1;
        }
        //释放进程属性对象
        pthread_attr_destroy(&attr);
        if (pthread_create(&thr2, NULL, MyFunc, &b) != 0)
        {
            printf("create thread is failed ! error message :%s
    ",
                    strerror(errno));
            return -1;
        }
        pthread_join(thr2, NULL);
        printf("main end
    ");
        return 0;
    }
  • 相关阅读:
    sql 日期格式化 比较全面
    SQL Server 2005 中的树形数据处理示例1
    Web网站的性能测试工具
    js实现时分秒
    sql查询远程数据库的表的数据并填充到本地数据库的表
    Windows 2003操作系统十四招加速大法
    window2003 server的一些优化设置_windows 2003
    解决html向aspx页面传值汉字乱码问题
    js快捷键大全 http://www.zhangxinxu.com/wordpress/?p=1667
    iis 重启命令
  • 原文地址:https://www.cnblogs.com/zhanggaofeng/p/5862287.html
Copyright © 2020-2023  润新知