`
tcspecial
  • 浏览: 901889 次
  • 性别: Icon_minigender_1
  • 来自: 深圳
社区版块
存档分类
最新评论

原子操作

阅读更多

 

一. Java volatile

volatile关键字可保证变量可见性,但是无法保证原子性,下面演示多线程修改共享变量Count场景。

  

/**
 * 共享变量在多线程下修改测试
 */
public class NonAtomicTest extends Thread {
	public static volatile int count = 0;
	
	public void increase(){
		count++;
	}
	
	public void run(){
		for(int i=0; i<10000; i++){
			increase();
		}
	}
	
	// main
	public static void main(String[] args) {
		Thread[] ths = new NonAtomicTest[20];
		
		for(int i=0; i<ths.length; i++){
			ths[i] = new NonAtomicTest();
			ths[i].start();
		}
		
		while(Thread.activeCount() > 1){
			Thread.yield();
		}
		
		System.out.println("Val: "+ count);
	}
}

 

执行上述代码,发现每次执行count的值都不同,均小于200000。原因count++非原子操作,字节码执行过程:

GETSTATIC count 	// 从内存加载count到栈
ICONST_1			// 从栈中读取count值
IADD				// 执行加法
PUTSTATIC count 	// 将执行结果存储至内存

 

对于上述问题,可对线程执行体加锁同步访问,但是加锁开销较大。Java中提供了AutomicInteger, AutomicLong 等原子操作类来处理上述问题,也是目前比较流行的无锁编程。原子操作由底层硬件 cmpxchg 指令支持,Linux 内核大量使用该指令。C++11也单独提供了原子类。

 

二. C++ 无锁编程

Linux下也提供原子操作API,C++11 std::aomic<T>模板均可进行无锁编程。

#include <iostream>
#include <vector>
#include <thread>
#include <atomic>
#include <mutex>

/// main
int main(int argc, char **argv)
{
	static volatile int Count = 0;
	std::mutex mutex;

	// 方案一:互斥锁
	auto fn1 = [&mutex, &Count]
	{
		for (int i=0; i<10000; i++)
		{
			std::lock_guard<std::mutex> lock(mutex);
			Count++;
		}
	};
	
	// 方案二:原子操作接口
	auto fn2 = [&Count]
	{
		for (int i=0; i<10000; i++)
		{
			__sync_fetch_and_add(&Count, 1);
			//__atomic_add_fetch(&Count, 1, __ATOMIC_SEQ_CST);
		}
	};
	
	static std::atomic<int> Count(0);
	
	// 方案三:原子类
	auto fn3 = [&Count]
	{
		for (int i=0; i<10000; i++)
		{
			std::atomic_fetch_add(&Count, 1);
		}
	};
	
	///
	std::vector<std::thread> threads;
	
	// 启动20个线程
	for(int i=0; i<20; i++)
	{
		threads.push_back(std::thread(fn2));
	}

	// 等待线程执行完成
	for (auto &th : threads)
	{
		th.join();
	}

	std::cout << "Val: " << Count << std::endl;	
	return 0;
}

 

g++ -o test test.c -std=c++11 -lpthread

上述三种方案均可打印200000

 

 

 

  

 

分享到:
评论

相关推荐

    kotlinx.atomicfu,在kotlin中使用原子操作的惯用方法.zip

    Kotlinx.AtomicFu是Kotlin社区的一个开源项目,它提供了在Kotlin中使用原子操作(Atomic Operations)的简便工具和库。这个项目主要是为了解决多线程环境下的并发问题,尤其是在非Java平台如JavaScript或者Native上...

    分布式Redis原子操作示例

    分布式Redis原子操作示例,近期项目中遇到分布式项目中多节点大并发操作redis同一个key。此案例利用java调用LUA脚本实现redis操作的原子性。分享出来大家参考。

    windows c++ 原子操作例子

    在Windows平台上,C++编程中使用原子操作(Atomic Operations)是为了保证多线程环境下的数据一致性,避免竞态条件和死锁等问题。原子操作是指在多线程环境下,该操作会被完整无中断地执行,不会被其他线程打断。...

    STM32的串口变量的原子操作问题

    串口方式:用串口接收中断方式接收,不是DMA. 遇到的问题:串口数据有帧丢失。 原因描述:在串口接收中断中接收到字节时变量size...实际的原因是对size的操作不是原子操作的,具体更改见文档。有相关程序和具体的分析。

    java多线程中的原子操作

    在Java多线程编程中,原子操作是一种非常关键的概念,它涉及到并发控制和线程安全。原子操作是指在不被其他线程中断的情况下,能够完整执行的一个或一系列操作。这样的操作在多线程环境中可以保证数据的一致性和完整...

    多线程程序中的原子操作

    多线程程序中的原子操作

    C++多线程原子操作

    C++多线程原子操作实现方法。很很详解!

    volatile和原子操作有没有关系,我的实验+别人论文

    探究volatile和原子操作的关系 在多线程编程中,volatile和原子操作都是非常重要的概念。volatile关键字用于告诉编译器不要对变量进行优化,而原子操作则是指不可中断的操作。在本文中,我们将探究volatile和原子...

    原子操作、信号量、读写信号量和自旋锁的API

    原子操作、信号量、读写信号量和自旋锁的API.希望能帮助大家

    同步之原子操作.pptx

    ARM 原子操作与同步机制 ARM 架构中的原子操作是指在多处理器系统中,确保对共享资源的访问是安全、可靠和高效的操作。原子操作是指在执行某个操作时,不允许其他处理器或线程干扰或中断该操作,直到该操作完成。 ...

    atomic_ops原子操作1

    原子操作 atomic_ops 介绍 atomic_ops 是 Linux 内核中的一种原子操作,用于实现原子 counter、Bit 操作和 spinlock 接口。下面将对 atomic_ops 的原子操作进行详细介绍。 atomic_t 类型 atomic_t 是一种原子...

    MongoDB原子操作.pdf

    在处理并发操作和数据更新时,MongoDB 提供了原子性保障,确保在单个文档级别的操作是不可分割的,即原子操作。虽然 MongoDB 不支持跨文档的事务,但对单个文档的修改、保存和删除等操作都是原子性的,保证了数据的...

    Linux驱动并发控制之位原子操作.pdf

    Linux 驱动并发控制之位原子操作 本文主要讲述 Linux 驱动并发控制中的位原子操作,包括其原理、常用的位原子操作函数、设备注册、驱动源码文件等。 一、位原子操作的原理 位原子操作是利用位操作来实现并发控制...

    linux下原子操作程序源码.zip

    在Linux系统中,原子操作(Atomic Operations)是编程中一种重要的技术,特别是在多线程和并发环境下,确保数据的一致性和完整性。它们提供了一种在不使用锁的情况下更新变量的方法,避免了竞态条件和死锁的问题。在...

    详解C++11原子类型与原子操作

    1.认识原子操作 原子操作就是在多线程程序中“最小的且不可并行化的”操作,意味着多个线程访问同一个资源时,有且仅有一个线程能对资源进行操作。通常情况下原子操作可以通过互斥的访问方式来保证,例如Linux下的...

    C++ 11 开发中的 Atomic 原子操作.rar_C++11、原子_atomic c++_c++ atomic使用_c++

    C++11引入了原子操作(Atomic Operations)作为标准库的一部分,这为多线程编程提供了重要的支持。原子操作在并发环境下确保了数据的完整性,防止了数据竞争和其他并发问题。下面将详细介绍C++11中`std::atomic`的...

    聊聊并发(5)原子操作的实现原理Java开发Java经验技

    在并发编程领域,原子操作是实现线程安全和高效代码的关键技术之一。本文将深入探讨Java开发中的原子操作实现原理,以及如何利用这些知识来优化Java应用。 首先,我们需要理解什么是原子操作。原子操作是指不可分割...

    zynq的linux驱动5-使用原子操作实现mio资源的竞争保护

    标题“zynq的linux驱动5-使用原子操作实现mio资源的竞争保护”表明我们将讨论如何通过使用原子操作来防止MIO(Multipurpose Input/Output)资源在多个进程间的竞争条件。描述进一步强调了目标,即在同一时刻只允许一...

    MongoDB原子操作与GridFS.pdf

    在 MongoDB 中,原子操作和GridFS是两个关键的概念,它们在处理大量数据和复杂操作时起着重要作用。 1. 原子操作: MongoDB 支持原子操作,这意味着数据库的操作是以最小单元执行的,要么全部完成,要么都不执行。...

Global site tag (gtag.js) - Google Analytics