线程同步机制(一)

线程同步机制(一)
  • 资源竞争
  • 互斥
  • 死锁
  • 信号量
  • 条件变量
资源竞争

存在一个任务队列,多个并发线程同时处理这些任务。每个线程在完成某项任务后,检查任务队列中是否有新任务。如果有就处理该任务,并将该任务从任务队列中删除

假设:两个线程碰巧完成各自任务,但队列中只有一个任务。

可能发生的情况:第一个线程发现任务队列非空,准备接收该任务,但没有完成全部设置。此时,操作系统碰巧中断该线程。第二个线程获得了执行权,也发现任务队列非空,同样准备接收该任务,但发现已经无法正确设置任务队列。

最坏情况:第一个线程已经从任务队列中摘取了任务,但是还没有将任务队列设置为空,第二个线程对任务队列的访问导致段错误,系统崩溃。

互斥

互斥(mutex)定义与性质:mutial exclusion

  • 相互独占锁,与二元信号量类似
  • 一次只有一个线程可以锁定一个数据对象,并访问
  • 只有该线程释放锁定,其他线程才能访问该数据对象

pthread_mutex_init()函数:初始化互斥

  • 原型:

    int pthread_mutex_init(pthread_mutex_t  *mutex,  const  pthread_mutex_attr_t *mutexattr);
    
  • 参数:mutex为互斥对象,mutexattr为互斥属性对象,NULL表示使用缺省属性

  • 可使用预定义宏PTHREAD_MUTEX_INITIALIZER初始化互斥

pthread_mutex_destroy()函数:销毁互斥

  • 原型:

    int pthread_mutex_destroy(pthread_mutex_t *mutex);
    

pthread_mutex_lock()函数:互斥加锁

  • 原型:

    int pthread_mutex_lock(pthread_mutex_t *mutex);
    
  • 如果无法锁定,则调用阻塞,至该互斥被解除锁定状态

pthread_mutex_trylock()函数:互斥加锁

  • 原型:

    int pthread_mutex_trylock(pthread_mutex_t *mutex);
    
  • 如果无法锁定,则立即返回,不阻塞

pthread_mutex_unlock()函数:互斥解锁

  • 原型 :

    int pthread_mutex_unlock(pthread_mutex_t *mutex);
    
使用互斥的流程
  • 定义pthread_mutex_t类型的变量,将其地址作为第一个参数传给pthread_mutex_init()函数;初始化函数只需调用一次
  • 锁定或尝试锁定该互斥;获得访问权后,执行正常程序代码;并在执行完毕后解锁
互斥属性
  • pshared属性:进程共享属性

    取值:

    PTHREAD_PROCESS_SHARED(跨进程共享)

    PTHREAD_PROCESS_PRIVATE(本进程内部共享)

  • type属性:互斥类型

    PTHREAD_MUTEX_NORMAL:普通锁

    • 被某个线程锁定后,其他请求加锁的进程将等待
    • 容易导致死锁
    • 解锁被其他线程锁定或已解锁的互斥,将导致不可预期的后果

    PTHREAD_MUTEX_ERRORCHEACK:检错锁

    • 线程对已被其他线程锁定的互斥加锁,将返回EDEADLK

    PTHREAD_MUTEX_RECURSIVE:递归锁*

    • 允许线程对互斥多次加锁;解锁次数必须与加锁次数匹配

    PTHREAD_MUTEX_DEFAULT:默认锁

    • 实现上可能为上述三种之一

    互斥属性函数

    int pthread_mutexattr_init(pthread_mutexattr_t *attr);	/*初始化互斥属性对象*/
    
    int pthread_mutexattr_destroy(pthread_mutexattr_t *attr);	/*销毁互斥属性对象*/
    
    int pthread_mutexattr_settype(pthread_mutexattr_t *attr, int kind);	/*设置typed属性*/
    
    int pthread_mutexattr_gettype(const  pthread_mutexattr_t  *attr, int *kind); /*获取type属性*/
    
    int pthread_mutexattr_getpshared(const pthread_mutexattr_t*attr, int *pshared);/*获取pshared属性*/
    
    int pthread_mutexattr_setpshared(pthread_mutexattr_t *attr,int pshared);	/*获取pshared属性*/
    
    互斥程序例子
    #include <list>
    #include <iostream>
    #include <pthread.h>
    using namespace std;
    
    struct Job {
      Job (int x = 0, int y = 0)
          : x (x), y (y)
      { }
      int x, y;
    };
    
    list<Job *> job_queue;
    pthread_mutex_t job_queue_mutex = PTHREAD_MUTEX_INITIALIZER;
    
    void ProcessJob (Job *job)
    {
      cout << "Thread " << (int) pthread_self ();
      cout << "processing (" << job->x << "," << job->y << ")\n";
    }
    
    //处理作业时需要加锁
    void *DequeueJob (void *arg)
    {
      while (true)
        {
          Job *job = nullptr;
          pthread_mutex_lock (&job_queue_mutex);
          if (!job_queue.empty ())
            {
              job = job_queue.front ();
              job_queue.pop_front ();
            }
          pthread_mutex_unlock (&job_queue_mutex);
          if (!job)
            {
              break;
            }
          ProcessJob (job);
          delete job, job = nullptr;
        }
      return nullptr;
    }
    
    void *EnqueueJob (void *arg)
    {
      Job *job = reinterpret_cast<Job *>(arg);
      pthread_mutex_lock (&job_queue_mutex);
      job_queue.push_back (job);
    
      cout << "Thread " << (int) pthread_self ();
      cout << " enqueueing (" << job->x << "," << job->y << ")\n";
    
      pthread_mutex_unlock (&job_queue_mutex);
      return nullptr;
    }
    
    int main ()
    {
      int i;
      pthread_t threads[8];
    
      for (i = 0; i < 5; ++i)
        {
          Job *job = new Job (i + 1, i + 2);
          pthread_create (&threads[i], nullptr, EnqueueJob, job);
        }
    
      for (i = 5; i < 8; ++i)
        {
          pthread_create (&threads[i], nullptr, DequeueJob, nullptr);
        }
    
      for (i = 0; i < 8; ++i)
        {
          pthread_join (threads[i], nullptr);
        }
    
      return 0;
    }
    
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值