02_线程,互斥锁的基础用法

Posted hello_zhao

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了02_线程,互斥锁的基础用法相关的知识,希望对你有一定的参考价值。

NPTL

zhao@VM-0-8-ubuntu ~ % getconf GNU_LIBPTHREAD_VERSION                                    [0]
NPTL 2.27

Linux内核不缺乏你进程和线程, 旨在用户层面上进行区分.

在linux下,线程是最小的执行单位;进程是最小的分配资源单位

线程基本用法

 pthread_t 线程号,Linux 使用无符号长整数表示

pthread_self 获取线程号
pthread_create 创建一个线程
pthread_join等待线程结束(此函数会阻塞),并回收线程资源.如果线程已经结束,那么该函数会立即返回。
pthread_detach线程与当前进程分离,当被分离的线程结束之后,系统会自动回收它的资源。
pthread_cancel杀死(取消)线程
pthread_equal 判断线程号 t1 和 t2 是否相等。

#include<stdio.h>
#include<string.h>
#include<stdlib.h>
#include<pthread.h>
#include<unistd.h>
//
////编译时需要指定连接线程库
////gcc pthread.c -pthread
//
void *run(void *arg) {
    printf("新线程被调用了...\\n");
    return NULL;
}

void *run2(void *arg) {
    printf("线程2被调用了...%p\\n", arg);
    return NULL;
}

void *run3(void *arg) {
    printf("join线程被调用了...%p\\n", arg);
    return NULL;
}

void *run4(void *arg) {
    printf("detach线程被调用了...\\n");
    return NULL;
}

void *run5(void *arg) {
    sleep(1);
    printf("线程退出被调用了...\\n");
    pthread_exit(NULL);
    return NULL;
}

void *run6(void *arg) {
    for (int i = 0; i < 8; i++) {
        sleep(1);
        printf("%d...\\n", i);
    }
    return NULL;
}

int main(){

    pthread_t tid = 0;

    //获取当前线程的线程号
    tid = pthread_self();

    printf("tid: %lu\\n",tid);

    if(pthread_equal(tid,pthread_self())){
        printf("两个线程ID相同\\n");
    }else{
        printf("两个线程ID不相同\\n");
    }

    //创建一个线程
    pthread_t ptid = 0;
    pthread_t ptid2 = 0;
    int ret = pthread_create(&ptid, NULL ,run, NULL);
    if(0!=ret){
        printf("pthread_create failed....\\n");
        return 1;
    }
    int ret2 = pthread_create(&ptid2,NULL,run2, (void*)0x3);
    if(0!=ret2){
        printf("pthread_create failed....\\n");
        return 1;
    }
    printf("main thread ...tid: %lu\\n",pthread_self());

    getchar();
    getchar();
    fflush(stdout);
    //--------线程阻塞实例------------

    void * retp = NULL;
    pthread_t tid3 = -1;
    int ret3 = -1;

    ret3 = pthread_create(&tid3,NULL,run3,NULL);
    if(0!= ret3){

    }
    //主线程阻塞直到ret3执行完
    ret3 = pthread_join(tid3,&retp);
    if(0!=ret3){
        printf("pthread_join fail...\\n");
        return 1;
    }
    printf("retp: %p\\n",retp);

    //------线程分离-----------
    pthread_t tid4 = -1;
    int ret4 = -1;
    ret4 = pthread_create(&tid4,NULL,run4,NULL);
    ret4 = pthread_detach(tid4);
    if(0!=ret4){
        printf("pthread_detach fail...\\n");
        return 1;
    }else{
        printf("pthread_detach success...\\n");
    }
    getchar();
    getchar();
    //------线程退出-----------
    pthread_t tid5 = -1;
    int ret5 = -1;
    ret5 = pthread_create(&tid5,NULL,run5,NULL);
    ret5 = pthread_join(tid5,NULL);
    if(0!=ret5){
        printf("pthread5 pthread_join fail...\\n");
        return 1;
    }else{
        printf("pthread5 pthread_join success...\\n");
    }
    getchar();
    getchar();
    //------线程取消-----------
    pthread_t tid6 = -1;
    int ret6 = -1;
    ret6 = pthread_create(&tid6,NULL,run6,NULL);
    ret6 = pthread_detach(tid6);
    if(0!=ret6){
        printf("pthread6 pthread_detach fail...\\n");
        return 1;
    }else{
        printf("pthread6 pthread_detach success...\\n");
    }
    sleep(3);
    printf("主线程睡眠3秒后取消子线程\\n");
    ret6 = pthread_cancel(tid6);
    if (ret6 != 0) {
        printf("pthread_cancel fail\\n");
        fprintf(stderr, "%s", strerror(ret6));
    }
    getchar();
    getchar();
    printf("main thread exit\\n");
    return 0;
}

互斥锁的基本用法

pthread_mutex_init
pthread_mutex_destroy
pthread_mutex_lock
pthread_mutex_unlock

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

pthread_mutex_t mutex;
void *fun1(void *arg) {
    //加锁
    pthread_mutex_lock(&mutex);
    for (int i = \'a\'; i <= \'z\'; ++i) {
        putchar(i);
        fflush(stdout);
        usleep(10000);
    }
    //解锁
    pthread_mutex_unlock(&mutex);
    return NULL;
}

void *fun2(void *arg) {
    //加锁
    pthread_mutex_lock(&mutex);
    for (int i = \'A\'; i <= \'Z\'; ++i) {
        putchar(i);
        fflush(stdout);
        usleep(10000);
    }
    //解锁
    pthread_mutex_unlock(&mutex);
    return NULL;
}

int main() {
    //初始化一个互斥锁
    pthread_mutex_init(&mutex,NULL);

    pthread_t t1;
    pthread_t t2;
    pthread_create(&t1, NULL, fun1, NULL);
    pthread_create(&t2, NULL, fun2, NULL);
    pthread_join(t1, NULL);
    pthread_join(t2, NULL);

    //销毁互斥锁
    pthread_mutex_destroy(&mutex);
    return 0;
}

//加锁前的输出:aABbcCdDEefFgGhHiIJjKklLmMNnoOPpqQrRSsTtUuVvWwXxYyZz
//加锁后的输出:abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ

条件变量

pthread_cond_t
pthread_cond_init 初始化
pthread_cond_destroy
pthread_cond_wait 释放该线程已持有的互斥锁, 并阻塞. 直到其他线程调用pthread_cond_signalpthread_cond_breadcast
pthread_cond_signal 通知pthread_cond_wait 阻塞的线程解除阻塞. 可以重新竞争互斥锁pthread_mutex_t

#include<stdio.h>
#include<string.h>
#include<stdlib.h>
#include<pthread.h>
#include<unistd.h>

//
////编译时需要指定连接线程库
////gcc pthread.c -pthread
//

pthread_mutex_t pmt;

pthread_cond_t pct;

typedef struct _node_t {
    int data;
    struct _node_t *next;
} node_t;

node_t *head = NULL;

void *producer(void *arg) {

    while (1) {
        pthread_mutex_lock(&pmt);
        node_t *newNode = (node_t *) (malloc(sizeof(node_t)));
        memset(newNode, 0, sizeof(node_t));

        newNode->data = rand() % 100 + 1;
        newNode->next = NULL;
        printf("produce %d\\n", newNode->data);
        newNode->next = head;
        head = newNode;
        pthread_cond_signal(&pct);
        pthread_mutex_unlock(&pmt);
        sleep(3);
    }
    pthread_exit(NULL);

    return NULL;
}

void *consumer(void *arg) {

    node_t *temp = NULL;
    while (1) {
        pthread_mutex_lock(&pmt);
        if (NULL == head) {
            printf("consume nothing\\n");
            pthread_cond_wait(&pct, &pmt);
        }
        temp = head;
        head = head->next;
        printf("consume %d\\n", temp->data);
        free(temp);

        pthread_mutex_unlock(&pmt);
    }
    pthread_exit(NULL);

    return NULL;
}


int main() {

    pthread_mutex_init(&pmt, NULL);
    pthread_cond_init(&pct, NULL);

    pthread_t pt1;
    pthread_t pt2;

    pthread_create(&pt1, NULL, producer, NULL);
    pthread_create(&pt2, NULL, consumer, NULL);

    pthread_join(pt1, NULL);
    pthread_join(pt2, NULL);

    pthread_mutex_destroy(&pmt);
    pthread_cond_destroy(&pct);

    return 0;
}

C++线程的基本使用

#include <iostream>
#include <thread>
#include <mutex>
#include <stdlib.h>
#include <chrono>

using namespace std;

mutex g_mutex;

void Deposit(mutex &m, int &money) {
    m.lock();
    for (int i = 0; i < 10; ++i) {
        money += 10;
    }
    m.unlock();
}

void WithDraw(mutex &m, int &money) {
    m.lock();
    for (int i = 0; i < 10; ++i) {
        money--;
    }
    m.unlock();
}

int main() {
    mutex m;
    int money = 1000;
    thread t1(Deposit, ref(m), ref(money));
    thread t2(WithDraw, ref(m), ref(money));

    t1.join();
    t2.join();
    cout << money << endl;
    return 0;
}

以上是关于02_线程,互斥锁的基础用法的主要内容,如果未能解决你的问题,请参考以下文章

为啥互斥锁没有被锁定

java中ReentrantReadWriteLock读写锁的使用

并发编程基础01-线程安全

synchronized互斥锁实例解析

Linux:详解多线程(线程安全互斥和死锁)

LockSupport.java 中的 FIFO 互斥代码片段