C11线程管理:原子变量&单调函数

1、原子变量

  C++11提供了原子类型std::atomic<T>,可以使用任意类型作为模板参数,使用原子变量就不需要使用互斥量来保护该变量,用起来更加简洁。

  举个例子,如果要做一个计数器,使用mutex时和使用原子变量依次如下:

//使用mutex
 struct  Counter
{
    int value;
    std::mutex mutex;

    void increment()
    {
        std::lock_guard<std::mutex> lock(mutex);
        ++value;
    }

    void decrement()
    {
        std::lock_guard<std::mutex> lock(mutex);
        --value;
    }

    int get()
    {
        return value;
    }
};

int main()
{

    return 0;
}

//使用原子变量
#include <atomic>

struct  Counter
{
    std::atomic<int> value;

    void increment()
    {
        ++value;
    }

    void decrement()
    {
        --value;
    }

    int get()
    {
        return value;
    }
};

2、call_once/once_flag

  单调函数就是在多线程环境中,保证某个函数只被调用一次,比如要初始化某个对象,而这个对象只能被初始化一次,就可以使用std::call_once来保证函数在多线程环境中只被调用一次。使用std::call_once时,需要一个once_flag作为call_once的入参。

作为call_once的入参。
#include <thread>
#include <iostream>
#include <mutex>             

std::once_flag flag;

void do_once()
{
    std::call_once(flag, [](){ std::cout << "Called once." << std::endl; });
}

int main()
{
    std::thread t1(do_once);
    std::thread t2(do_once);
    std::thread t3(do_once);

    t1.join();
    t2.join();
    t3.join();

    return 0;
}
//输出:
Called once.
时间: 2024-07-30 03:08:19

C11线程管理:原子变量&单调函数的相关文章

C11线程管理:条件变量

1.简介 C11提供另外一种用于等待的同步机制,它可以阻塞一个或者多个线程,直到收到另外一个线程发出的通知或者超时,才会唤醒当前阻塞的线程.条件变量要和互斥量配合起来使用. condition_variable,配合std::unique_lock<std::mutex>进行wait操作. condition_variable_any,和任意带有lock.unlock语意 的mutex搭配使用,比较灵活,但是效率比condition_variable低. 条件变量的使用过程如下: a.拥有条件

C11线程管理:互斥锁

1.概述 锁类型 c11提供了跨平台的线程同步手段,用来保护多线程同时访问的共享数据. std::mutex,最基本的 Mutex 类,独占的互斥量,不能递归使用. std::time_mutex,带超时的独占互斥量,不能递归使用. std::recursive_mutex,递归互斥量,不带超时功能. std::recursive_timed_mutex,带超时的递归互斥量. lock类型 std::lock_guard,与 Mutex RAII 相关,方便线程对互斥量上锁. std::uniq

Java并发——原子变量和原子操作与阻塞算法

十五年前,多处理器系统是高度专用系统,要花费数十万美元(大多数具有两个到四个处理器).现在,多处理器系统很便宜,而且数量很多,几乎每个主要微处理器都内置了多处理支持,其中许多系统支持数十个或数百个处理器. 要使用多处理器系统的功能,通常需要使用多线程构造应用程序.但是正如任何编写并发应用程序的人可以告诉你的那样,要获得好的硬件利用率,只是简单地在多个线程中分割工作是不够的,还必须确保线程确实大部分时间都在工作,而不是在等待更多的工作,或等待锁定共享数据结构. 问题:线程之间的协调 如果线程之间 

java并发编程(8)原子变量和非阻塞的同步机制

原子变量和非阻塞的同步机制 一.锁的劣势 1.在多线程下:锁的挂起和恢复等过程存在着很大的开销(及时现代的jvm会判断何时使用挂起,何时自旋等待) 2.volatile:轻量级别的同步机制,但是不能用于构建原子复合操作 因此:需要有一种方式,在管理线程之间的竞争时有一种粒度更细的方式,类似与volatile的机制,同时还要支持原子更新操作 二.CAS 独占锁是一种悲观的技术--它假设最坏的情况,所以每个线程是独占的 而CAS比较并交换:compareAndSwap/Set(A,B):我们认为内存

java线程管理

java线程管理 参见: http://harmony.apache.org/subcomponents/drlvm/TM.html 1. 修订历史 2. 关于本文档 2.1. 目的 2.2. 面向的读者 2.3. 文档约定 2.4. 文档使用 3. 概览 3.1. 主要特点 3.2. VM中的线程管理器 3.3. 可移植性 4. 体系结构 4.1. 对外接口 4.1.1. Native 接口 4.1.2. Java* 接口 4.2. 数据结构 4.3. 线程控制结构 4.3.1.Native

java并发编程11.原子变量与非阻塞同步机制

在非阻塞算法中不存在死锁和其他活跃性问题. 在基于锁的算法中,如果一个线程在休眠或自旋的同时持有一个锁,那么其他线程都无法执行下去,而非阻塞算法不会受到单个线程失败的影响. 锁的劣势 许多JVM都对非竞争锁获取和释放操作进行了极大的优化,但如果有多个线程同时请求锁,那么JVM就需要借助操作系统地功能.如果出现了这种情况,那么一些线程将被挂起并且在稍后恢复运行.当线程恢复执行时,必须等待其他线程执行完它们的时间片以后,才能被调度执行.在挂起和恢复线程等过程中存在着很大的开销,并且通常存在着较大时间

三、原子变量与CAS算法

原子变量:jdk1.5 后 java.util.concurrent.atomic 包下提供了常用的原子变量: - AtomicBoolean - AtomicInteger - AtomicLong - AtomicReference - AtomicIntegerArray - AtomicLongArray - AtomicMarkableReference - AtomicReferenceArray - AtomicStampedReference 1.以上类中的变量都是volatil

原子变量与CAS算法

上一节讨论了 volatile关键字,volatile关键字修饰的作用是不具有 "原子性" 和 "互斥性的" 例如 i++ 操作 就不是一个原子性的操作,i++ 其实分为3个步骤进行 "读-改-写" int temp = i; i = i + 1; i= temp; 先看一段代码: package com.java.juc; public class TestAtomicDemo { public static void main(String[

J.U.C中的原子变量

在开发过程中,很多时候都需要用到原子的递增递减操作:而我们知道,常用的i ++ 和 i -- 等操作都不是原子的,它包含了三步操作(读-改-写):首先,读取变量i的值,其次将i执行 +1 或者 -1 操作,最后,将计算后的结果赋值给i:通常情况下,只有加锁才能保证 i ++ 和 i -- 等操作的原子性.值得关注的是,在JDK1.5及之后的所有版本,java.concurrent.util.atomic包下给我们提供了原子变量,原子变量支持原子的递增和递减操作.这里,针对原子变量的底层实现原理及