线程同步和安全

来源:互联网 发布:金山数据恢复大师 编辑:程序博客网 时间:2024/06/01 08:03


1.同步概念:

            多进程或者多线程访问临界资源时,必须进行同步控制。多进程或者多线程的执行并不完全是绝对的并行运行,有可能主线程需要等待函数线程的某些条件的发生。

2.多线程之间有几个特殊的临界资源:

             全局数据、堆区数据、文件描述符 多线程之间共用

3.线程间同步控制方式:
      1)信号量 #include <semaphore.h>


       ①获取: int sem_init(sem_t *sem, int shared , int value); 返回值: 成功 0       失败-1

                             sem:   是一个 sem_t 类型指针,指向信号量对象。 

                             shared: 是否能在多进程间共享, Linux 不支持, 0
                             value: 信号量的初始值
     ② P 操作: int sem_wait(sem_t *sem); // 阻塞运行


     ③V 操作: int sem_post(sem_t *sem);


     ④删除: int sem_destroy(sem_t *sem);
      练习:主线程循环获取用户输入, 函数线程统计用户输入的字符个数(统计一次需要 5 秒)。

  代码:






     2)互斥锁

     3)条件变量

4.线程安全(可重入函数)


           有些库函数会使用线程间共享的数据,如果没有同步控制,线程操作就是不安全的,所以,我们使用这样一些函数时,就必须使用其安全的版本 ---》可重入函数

          

            以strtok为列:如果使用strtok则下面程序输出1abcdefg


                                        可重入函数strotok_r

      

                  此时输出1a2b3c.....

注意:函数线程创建出来以后,函数线程与主线程同时执行,主线程以 exit 结束,则进程结束,所有的函数线程都将结束。

5.线程中 fork 的使用,锁的变化
           在线程中调用 fork 函数,子进程只会启用调用 fork 函数的那条线程,其他线程 不会启用。子进程会继承其父进程的锁以及锁的状态,但是父子进程用的不是同一把锁,        父进程解锁并不会影响到子进程的锁,所以子进程有可能死锁!!!
             pthread_atfork(void (*prepare)(void), void (*parent)(void ), void (*child)(void));

            指定在 fork 调用之后,创建子进程之前, 调用 prepare 函数,获取所有的锁,然后创建子进程, 子进程创建以后,父进程环境中调用 parent 解所有的锁,子进程环境中调用 child 解所有的锁,然后 fork 函数再返回。这样保证了 fork 之后,子进程拿到的锁都是解锁状态,避免死锁。



原创粉丝点击