精华内容
下载资源
问答
  • //原子Integer 实现计数器 public class AtomicCounter { // 原子Integer递增对象 public static AtomicInteger atomicInteger = new AtomicInteger(0); public static void main(String[] args) {...

    package class10;

    import java.util.concurrent.ExecutorService;

    import java.util.concurrent.Executors;

    //使用synchronized 实现计数器

    public class SyncCounter {

    private int count = 0;

    public synchronized void increase() {

    count++;

    }

    public int getCount() {

    return count;

    }

    public static void main(String[] args) {

    final SyncCounter aor = new SyncCounter();

    // 线程池

    ExecutorService exec = Executors.newCachedThreadPool();

    // 模拟20个客户端访问

    for (int index = 0; index 

    Runnable run = new Runnable() {

    public void run() {

    aor.increase();

    int result = aor.getCount();

    System.out.println(result);

    }

    };

    exec.execute(run);

    }

    // 退出线程池

    exec.shutdown();

    }

    }

    package class10;

    import java.util.concurrent.ExecutorService;

    import java.util.concurrent.Executors;

    import java.util.concurrent.atomic.AtomicInteger;

    //原子Integer 实现计数器

    public class AtomicCounter {

    // 原子Integer递增对象

    public static AtomicInteger atomicInteger = new AtomicInteger(0);

    public static void main(String[] args) {

    // 线程池

    ExecutorService exec = Executors.newCachedThreadPool();

    // 模拟50个客户端访问

    for (int index = 0; index 

    Runnable run = new Runnable() {

    public void run() {

    atomicInteger.getAndIncrement();

    System.out.println(atomicInteger);

    }

    };

    exec.execute(run);

    }

    // 退出线程池

    exec.shutdown();

    System.out.println(atomicInteger);

    }

    }

    package class10;

    import java.util.concurrent.ExecutorService;

    import java.util.concurrent.Executors;

    import java.util.concurrent.locks.ReentrantLock;

    //使用ReentrantLock实现计数器

    public class ReentrantLockTest {

    private ReentrantLock lock = new ReentrantLock();

    private int count;

    public void increase() {

    lock.lock();

    count++;

    try {

    try {

    Thread.sleep(10);

    } catch (InterruptedException e) {

    System.err.println(Thread.currentThread().getName() + " interrupted");

    Thread.currentThread().interrupt();

    }

    } finally {

    lock.unlock();

    }

    }

    public int getCount() {

    return count;

    }

    public static void main(String[] args) {

    final ReentrantLockTest reentrantLockTest = new ReentrantLockTest();

    // 线程池

    ExecutorService exec = Executors.newCachedThreadPool();

    // 模拟20个客户端访问

    for (int index = 0; index 

    Runnable run = new Runnable() {

    public void run() {

    reentrantLockTest.increase();

    int result = reentrantLockTest.getCount();

    System.out.println(result);

    }

    };

    exec.execute(run);

    }

    // 退出线程池

    exec.shutdown();

    System.out.println(reentrantLockTest.getCount());

    }

    }

    展开全文
  • C++编程--原子变量

    千次阅读 2019-06-06 17:38:18
    原子变量的操作是原子操作,能保证在任何情况下都不被打断,是线程安全的,不需要加锁。 在新标准C++11,引入了原子操作的概念,并通过这个新的头文件提供了多种原子操作数据类型,例如,atomic_bool,atomic_int...

    应用场景:多线程下的计数等等。

    对原子变量的操作是原子操作,能保证在任何情况下都不被打断,是线程安全的,不需要加锁。

    在新标准C++11,引入了原子操作的概念,并通过这个新的头文件提供了多种原子操作数据类型,例如,atomic_bool,atomic_int等等,如果我们在多个线程中对这些类型的共享资源进行操作,编译器将保证这些操作都是原子性的,也就是说,确保任意时刻只有一个线程对这个资源进行访问,编译器将保证,多个线程访问这个共享资源的正确性。从而避免了锁的使用,提高了效率。

    C++11下的用法:

    头文件:#include<atomic>

    atomic_int count(0);//声明并初始化

    使用方法和普通的变量使用方法相同,只是它的操作已经被封装成类似原子操作,虽然实际上是封装后的,不是真正内核意义上的原子操作,但是这也简化了编程。

    展开全文
  • 多线程操作会带来不一致性,为了实现一直性。我们可以用关键字:synchronized同步对象或者volatile轻量级、内存可见性。 两个关键字使用对比: 1、synchronized比较重...java已经实现了很多原子操作类:在java.ut...

    多线程操作会带来不一致性,为了实现一直性。我们可以用关键字:synchronized同步对象或者volatile轻量级、内存可见性。

    两个关键字使用对比:

    1、synchronized比较重,属于悲观锁机制,造成冲突大,线程间的上下文切换多,资源浪费。

    比如我们就实现计数操作。

    2、volatile轻量级内存可见性,非阻塞式,性能更高。

    java已经实现了很多原子操作类:在java.util.concurrent包里

     AtomicBoolean:原子Boolean类型
     AtomicInteger:原子Integer类型
     AtomicLong:原子Long类型
     AtomicReference:原子引用类型

    及相应的数组类型:

    AtomicIntegerArray
    AtomicLongArray
    AtomicReferenceArray

    为了便于以原子方式更新对象中的字段,还有如下的类:
        AtomicIntegerFieldUpdater
        AtomicLongFieldUpdater
        AtomicReferenceFieldUpdater
    AtomicReference还有两个类似的类,在某些情况下更为易用:

        AtomicMarkableReference
        AtomicStampedReference

    实现原理就是用到volatile关键字声明变量。

    转载于:https://www.cnblogs.com/zhaoguo435/p/6607057.html

    展开全文
  • 原子计数【转】

    2013-01-08 16:53:32
     当然我们知道,count++这种操作不是原子的。一个自加操作,本质是分成三步的:  1 从缓存取到寄存器  2 在寄存器加1  3 存入缓存。  由于时序的因素,多个线程操作同一个全局变量,会出现问题。这也是并发...
    最近编码需要实现多线程环境下的计数器操作,统计相关事件的次数。下面是一些学习心得和体会。不敢妄称原创,基本是学习笔记。遇到相关的引用,我会致谢。
    

      当然我们知道,count++这种操作不是原子的。一个自加操作,本质是分成三步的:

      1 从缓存取到寄存器

      2 在寄存器加1

      3 存入缓存。

      由于时序的因素,多个线程操作同一个全局变量,会出现问题。这也是并发编程的难点。在目前多核条件下,这种困境会越来越彰显出来。

      最简单的处理办法就是加锁保护,这也是我最初的解决方案。看下面的代码:

      pthread_mutex_t count_lock = PTHREAD_MUTEX_INITIALIZER;

      pthread_mutex_lock(&count_lock);

      global_int++;

      pthread_mutex_unlock(&count_lock);

      后来在网上查找资料,找到了__sync_fetch_and_add系列的命令,发现这个系列命令讲的最好的一篇文章,英文好的同学可以直接去看原文。Multithreaded simple data type access and atomic variables

      __sync_fetch_and_add系列一共有十二个函数,有加/减/与/或/异或/等函数的原子性操作函数,__sync_fetch_and_add,顾名思义,现fetch,然后自加,返回的是自加以前的值。以count = 4为例,调用__sync_fetch_and_add(&count,1),之后,返回值是4,然后,count变成了5.

      有__sync_fetch_and_add,自然也就有__sync_add_and_fetch,呵呵这个的意思就很清楚了,先自加,在返回。他们哥俩的关系与i++和++i的关系是一样的。被谭浩强他老人家收过保护费的都会清楚了。

      有了这个宝贝函数,我们就有新的解决办法了。对于多线程对全局变量进行自加,我们就再也不用理线程锁了。下面这行代码,和上面被pthread_mutex保护的那行代码作用是一样的,而且也是线程安全的。

      __sync_fetch_and_add( &global_int, 1 );

      下面是这群函数的全家福,大家看名字就知道是这些函数是干啥的了。

      type __sync_fetch_and_add (type *ptr, type value);

      type __sync_fetch_and_sub (type *ptr, type value);

      type __sync_fetch_and_or (type *ptr, type value);

      type __sync_fetch_and_and (type *ptr, type value);

      type __sync_fetch_and_xor (type *ptr, type value);

      type __sync_fetch_and_nand (type *ptr, type value);

      type __sync_add_and_fetch (type *ptr, type value);

      type __sync_sub_and_fetch (type *ptr, type value);

      type __sync_or_and_fetch (type *ptr, type value);

      type __sync_and_and_fetch (type *ptr, type value);

      type __sync_xor_and_fetch (type *ptr, type value);

      type __sync_nand_and_fetch (type *ptr, type value);

      需要提及的是,这个type不能够瞎搞。下面看下__sync_fetch_and_add反汇编出来的指令,

      804889d: f0 83 05 50 a0 04 08 lock addl $0x1,0x804a050

      我们看到了,addl前面有个lock,这行汇编指令码前面是f0开头,f0叫做指令前缀,Richard Blum

      老爷子将指令前缀分成了四类,有兴趣的同学可以看下。其实我也没看懂,intel的指令集太厚了,没空看。总之老爷子解释了,lock前缀的意思是对内存区域的排他性访问。

      ? Lock and repeat prefixes

      ? Segment override and branch hint prefixes

      ? Operand size override prefix

      ? Address size override prefix

      前文提到,lock是锁FSB,前端串行总线,front serial bus,这个FSB是处理器和RAM之间的总线,锁住了它,就能阻止其他处理器或者core从RAM获取数据。当然这种操作是比较费的,只能操作小的内存可以这样做,想想我们有memcpy ,如果操作一大片内存,锁内存,那么代价就太昂贵了。所以前文提到的_sync_fetch_add_add家族,type只能是int long ,long long(及对应unsigned类型)。

      下面提供了函数,是改造的Alexander Sundler的原文,荣誉属于他,我只是学习他的代码,稍微改动了一点点。比较了两种方式的耗时情况。呵呵咱是菜鸟,不敢枉自剽窃大师作品。向大师致敬。

      #define _GNU_SOURCE

      #include

      #include

      #include

      #include

      #include

      #include

      #include

      #include

      #include

      #include

      #define INC_TO 1000000 // one million...

      __u64 rdtsc()

      {

      __u32 lo,hi;

      __asm__ __volatile__

      (

      "rdtsc":"=a"(lo),"=d"(hi)

      );

      return (__u64)hi<<32|lo;

      }

      int global_int = 0;

      pthread_mutex_t count_lock = PTHREAD_MUTEX_INITIALIZER;

      pid_t gettid( void )

      {

      return syscall( __NR_gettid );

      }

      void *thread_routine( void *arg )

      {

      int i;

      int proc_num = (int)(long)arg;

      __u64 begin, end;

      struct timeval tv_begin,tv_end;

      __u64 timeinterval;

      cpu_set_t set;

      CPU_ZERO( &set );

      CPU_SET( proc_num, &set );

      if (sched_setaffinity( gettid(), sizeof( cpu_set_t ), &set ))

      {

      perror( "sched_setaffinity" );

      return NULL;

      }

      begin = rdtsc();

      gettimeofday(&tv_begin,NULL);

      for (i = 0; i < INC_TO; i++)

      {

      // global_int++;

      __sync_fetch_and_add( &global_int, 1 );

      }

      gettimeofday(&tv_end,NULL);

      end = rdtsc();

      timeinterval =(tv_end.tv_sec - tv_begin.tv_sec)*1000000 +(tv_end.tv_usec - tv_begin.tv_usec);

      fprintf(stderr,"proc_num :%d,__sync_fetch_and_add cost %llu CPU cycle,cost %llu us\n", proc_num,end-begin,timeinterval);

      return NULL;

      }

      void *thread_routine2( void *arg )

      {

      int i;

      int proc_num = (int)(long)arg;

      __u64 begin, end;

      struct timeval tv_begin,tv_end;

      __u64 timeinterval;

      cpu_set_t set;

      CPU_ZERO( &set );

      CPU_SET( proc_num, &set );

      if (sched_setaffinity( gettid(), sizeof( cpu_set_t ), &set ))

      {

      perror( "sched_setaffinity" );

      return NULL;

      }

      begin = rdtsc();

      gettimeofday(&tv_begin,NULL);

      for(i = 0;i

      {

      pthread_mutex_lock(&count_lock);

      global_int++;

      pthread_mutex_unlock(&count_lock);

      }

      gettimeofday(&tv_end,NULL);

      end = rdtsc();

      timeinterval =(tv_end.tv_sec - tv_begin.tv_sec)*1000000 +(tv_end.tv_usec - tv_begin.tv_usec);

      fprintf(stderr,"proc_num :%d,pthread lock cost %llu CPU cycle,cost %llu us\n",proc_num,end-begin ,timeinterval);

      return NULL;

      }

      int main()

      {

      int procs = 0;

      int i;

      pthread_t *thrs;

      // Getting number of CPUs

      procs = (int)sysconf( _SC_NPROCESSORS_ONLN );

      if (procs < 0)

      {

      perror( "sysconf" );

      return -1;

      }

      thrs = malloc( sizeof( pthread_t ) * procs );

      if (thrs == NULL)

      {

      perror( "malloc" );

      return -1;

      }

      printf( "Starting %d threads...\n", procs );

      for (i = 0; i < procs; i++)

      {

      if (pthread_create( &thrs[i], NULL, thread_routine,

      (void *)(long)i ))

      {

      perror( "pthread_create" );

      procs = i;

      break;

      }

      }

      for (i = 0; i < procs; i++)

      pthread_join( thrs[i], NULL );

      free( thrs );

      printf( "After doing all the math, global_int value is: %d\n", global_int );

      printf( "Expected value is: %d\n", INC_TO * procs );

      return 0;

      }

      通过我的测试发现:

      Starting 4 threads...

      proc_num :2,no locker cost 27049544 CPU cycle,cost 12712 us

      proc_num :0,no locker cost 27506750 CPU cycle,cost 12120 us

      proc_num :1,no locker cost 28499000 CPU cycle,cost 13365 us

      proc_num :3,no locker cost 27193093 CPU cycle,cost 12780 us

      After doing all the math, global_int value is: 1169911

      Expected value is: 4000000

      Starting 4 threads...

      proc_num :2,__sync_fetch_and_add cost 156602056 CPU cycle,cost 73603 us

      proc_num :1,__sync_fetch_and_add cost 158414764 CPU cycle,cost 74456 us

      proc_num :3,__sync_fetch_and_add cost 159065888 CPU cycle,cost 74763 us

      proc_num :0,__sync_fetch_and_add cost 162621399 CPU cycle,cost 76426 us

      After doing all the math, global_int value is: 4000000

      Expected value is: 4000000

      Starting 4 threads...

      proc_num :1,pthread lock cost 992586450 CPU cycle,cost 466518 us

      proc_num :3,pthread lock cost 1008482114 CPU cycle,cost 473998 us

      proc_num :0,pthread lock cost 1018798886 CPU cycle,cost 478840 us

      proc_num :2,pthread lock cost 1019083986 CPU cycle,cost 478980 us

      After doing all the math, global_int value is: 4000000

      Expected value is: 4000000

      1 不加锁的情况下,不能返回正确的结果

      测试程序结果显示,正确结果为400万,实际为1169911.

      2 线程锁和原子性自加都能返回正确的结果。

      3 性能上__sync_fetch_and_add,完爆线程锁。

      从测试结果上看, __sync_fetch_and_add,速度是线程锁的6~7倍


    展开全文
  • 原子计数操作 — _syn_fetch_and_add等12个操作         多线程计数操作,共享状态或者统计相关时间次数,这些都需要在多线程之间共享变量和修改变量,如此就需要在多线 程间对该变量进行互斥操作和访问....
  • 最近自己做了一些涉及多线程编程的项目,其中就涉及到多线程间计数操作、共享状态或者统计相关时间次数,这些都需要在多线程之间共享变量和修改变量,如此就需要在多线程间对该变量进行互斥操作和访问。  通常遇到...
  • linux 驱动之原子操作

    2019-11-30 16:55:23
    2、对原子变量进行原子操作(计数) 1)、原子变量自增/自减 2)、原子变量加/减 3)、设置原子变量的值 4)、获取原子变量的值 5)、操作并测试 6)、操作并返回 四、参考代码 一、原子操作介绍 什么叫...
  • 多线程间计数操作、共享状态或者统计相关时间次数,这些都需要在多线程之间共享变量和修改变量,如此就需要在多线程间对该变量进行互斥操作和访问。 通常遇到多线程互斥的问题,首先想到的就是加锁lock,通过加...
  • 举个例子:如果一个变量 Long value =0; 首先说一下正常情况下的加减操作:value+=1; 1:系统从Value的空间取出值,并动态生成一个空间来存储取出来的值; 2:将取出来的值和1作加法,并且将和放回Valu
  • 顾名思义,引用计数bytebuf基类。 在介绍这个类之前,先介绍几个点预热一下。 AtomicIntegerFieldUpdater 整型字段的更新器,保证更新integer字段原子性操作 CAS :compareAndSet,获取当前变量的值,根据变量计算...
  • 根据jdk提供的原生的原子变量计数。 package test201603; import java.util.ArrayList; import java.util.List; import java.util.concurrent.atomic.AtomicInteger; /** * 计数器 */ public cl
  • 秒杀多线程第三篇 原子操作 Interlocked系列函数

    万次阅读 多人点赞 2012-04-09 09:08:16
    这也非常类似于统计一个网站每天有多少用户登录,每个用户登录用一个线程模拟,线程运行时会将一个表示计数变量递增。程序在最后输出计数的值表示有今天多少个用户登录,如果这个值不等于我们启动的线程个数,那显
  • 实现原子计数器

    2020-02-11 11:00:23
    定义一个单例模式的对象,声明一个原子计数对象: public class Singleton { //定义自增变量 public static AtomicInteger count = new AtomicInteger(0); //累加 public static void increase() { count....
  • 016 原子

    2018-05-05 23:19:00
    在我们之前的计数程序之中,我们知道只要保证count++是一个原子性的操作就能保证程序的线程安全性.  当然这种常用的功能在jdk5中就出现了,这就是原子类. 原子类都是JUC包下atomic之中,类的数量比较多. 二 . ...
  • 7.4 原子操作原子操作指的是在执行过程中不会被别的代码路径所中断的操作。Linux内核提供一系列函数来实现内核中的原子操作,这些函数分为两类,分别针对位和整型变量进行原子操作。...设置原子变量的值vo...
  • C++原子操作之windows

    2018-07-10 14:40:36
    在多线程环境下要计数,需要保证:计数变量的一致性和线程安全才能保证多线程环境下计数正确。 现在就来简短的说一说windows的C++原子操作。 ——-所谓原子访问,指的是一个线程在访问某个资源的同时能够保证没有...
  • 在多线程环境下要计数,需要保证:计数变量的一致性和线程安全才能保证多线程环境下计数正确。 原子计数正是提供了此需求的功能,保证计数操作未执行完毕时绝不会被其他任何实务或事件打断,下面是原子计数器 for ...
  • Java变量线程安全

    千次阅读 2019-07-11 11:49:58
    volatile、ThreadLocal使用...解释:volatile修饰的变量当前状态和修改后状态不能产生依赖(即不能用来计数,实现自增自减)。例: public static volatile int i=0;随后执行i++,不是线程安全的。 该变量没有包含在...
  • java多线程笔记–Atomic原子操作类 文章目录java多线程笔记--Atomic原子操作类1Atomic原子操作多线程计数... * Atomic原子操作类,用法简单,线程安全的更新变量 * @Author: * @Date: 2019/5/14 23:56 */ public ...
  • 原子操作与volitile

    2011-12-31 01:19:59
    近来研究Nebula3引擎,发现引用计数机制里面谈到了原子操作,而变量则是用volitile修饰的。感觉两者之间应该有某种联系,研究了下发现果然如此。。。。  首先要知道,何谓原子操作。。在我们看来,原子操作就是不...
  • 大家在工作中肯定遇到过计数统计需求,单线程的情况下count直接定义int型就行,可是在多线程并发下会产生多个线程同时count++的情况,那么这种情况就需要用到AtomicInteger来保证int型变量操作的原子性。 ...
  • 计数成员变量使用原子操作 文件名: Ref_count.hpp 名称空间: custom 类名: Ref_count 包含的头文件: cstddef 和 atomic 成员类型 类型 作用 count_type std::size_t 计数的类型 类型 成员变量 作用 ...
  • 多线程计数器——原子操作

    千次阅读 2014-09-28 17:33:50
    众所周知,多线程下计数存在着计数不正确的问题。这个问题的根源在于多个线程对同一个变量可以同时访问(修改)。这样就造成了修改后的结果不一致。  首先在这里先强调一点,volatile 关键字并不能提供多线程安全...
  • C++原子操作之linux

    2018-07-10 12:08:18
    众所周知,多线程下计数存在着计数不正确的问题。这个问题的根源在于多个线程对同一个变量可以同时访问(修改)。这样就造成了修改后的结果不一致。 首先在这里先强调一点,volatile 关键字并不能提供多线程安全...
  • 今天在看正点原子的delay.c的文件的时候,看到了...首先得明白变量fac_us的含义是1微秒所要计数的次数,如果你明白了这个就好解释了。 由SysTick_CLKSourceConfig(SysTick_CLKSource_HCLK_Div8);可知,systick的...
  • 下面是类似于统计一个网站每天有多少用户登录,每个用户登录用一个线程模拟,线程运行时会将一个表示计数变量递增。程序在最后输出计数的值表示有今天多少个用户登录,如果这个值不等于我们启动的线程个数,那显然...
  • effective java 第66条内容说到,累计计数i++同步问题一种是用sync修饰符进行同步操作另一种是使用AtomicXXX变量,如AtomicLong 的 getAndIncrement方法好奇AtomicLong的实现,原以为也是进行同步锁操作实现的原子性...

空空如也

空空如也

1 2 3 4 5 ... 9
收藏数 161
精华内容 64
关键字:

原子变量计数