热门标签 | HotTags
当前位置:  开发笔记 > 编程语言 > 正文

web线程安全中的原子操作是什么

这篇文章主要介绍“web线程安全中的原子操作是什么”,在日常操作中,相信很多人在web线程安全中的原子操作是什么问题上存在疑惑,小编查阅了各

这篇文章主要介绍“web线程安全中的原子操作是什么”,在日常操作中,相信很多人在web线程安全中的原子操作是什么问题上存在疑惑,小编查阅了各式资料,整理出简单好用的操作方法,希望对大家解答”web线程安全中的原子操作是什么”的疑惑有所帮助!接下来,请跟着小编一起来学习吧!

原子操作

原子性就是指该操作是不可再分的。不论是多核还是单核,具有原子性的量,同一时刻只能有一个线程来对它进行操作。 原子操作可以是一个步骤,也可以是多个步骤,但是其顺序不可以被打乱,也不可以被切割而只执行其中的一部分(不可中断性)。 将操作视作一个整体,资源在该次操作中保持一致,这是原子性的核心特征。

首先我们来看一个非原子操作的示例:

public class Counter {

  volatile int i = 0;

  public void increament() {
    i++;
  }
}

测试代码:

public class CouterTest {

  public static void main(String[] args) throws InterruptedException {
    final Counter counter = new Counter();
    for (int i = 0; i < 6; i++) {
      new Thread(
              new Runnable() {
                @Override
                public void run() {
                  for (int j = 0; j < 10000; j++) {
                    counter.increament();
                  }
                  System.out.println("done...");
                }
              })
          .start();
    }
    Thread.sleep(6000L);
    System.out.println(counter.i);
  }
}

正确情况下以上测试代码我们启动了6个线程每个增加10000,结果输出应该是60000,但实际结果却是小于60000的,其原因就在于i++并不是原子的操作,通过反编译我们可以知道它实际上在JVM运行时是4个指令。 web线程安全中的原子操作是什么

那么如何才能让以上代码正确运行那?

  1. 通过加锁的形式,可以是synchronized加锁,也可以是ReentrantLock加锁. 这种方式是通过加锁的方式使其变成串行的单线程操作,效果不是太高。

syncchronized 加锁代码示例

public class Counter {

  volatile int i = 0;

  public synchronized void increament() {
    i++;
  }
}

ReentrantLock加锁代码示例:

public class Counter {

  volatile int i = 0;

  Lock lock = new ReentrantLock();

  public void increament() {
    lock.lock();
    i++;
    lock.unlock();
  }
}
  1. 通过JDK提供的原子操作的API中的AtomicInteger,这种方式其底层是通过CAS操作,仍是使用多线程进行,所以效率会相对较高。

AtomicInteger代码示例:

public class Counter {

  AtomicInteger i= new AtomicInteger();

  public void increament() {
    i.incrementAndGet();
  }
}

CAS(Compare and swap)

Compare and swap 比较和交换,属于硬件同步原语,处理器提供了基本内存操作的原子性保证。 CAS 操作包含三个操作数--内存位置(V),预期原值(A)和新值(B)。 如果内存位置的值与预期原值相匹配,那么处理器会自动将该位置值交换成新值,如果不匹配,即内存位置的值了变化则不做交换。 Java中的sun.misc.Unsafe类提供了compareAndSwapIntcompareAndSwapLong等几个方法实现CAS, 其代码示例如下:

// JDK提供的原子操作API其原理基本如此
public class CounterUnsafe {

  volatile int i = 0;

  private static Unsafe unsafe = null;

  // i字段地址偏移量
  private static long valueOffset;

  static {
    //    unsafe = Unsafe.getUnsafe();  该方式并不可用
    try {
      Field field = Unsafe.class.getDeclaredField("theUnsafe");
      field.setAccessible(true);
      unsafe = (Unsafe) field.get(null);

      Field fieldi = CounterUnsafe.class.getDeclaredField("i");
      // 获取字段i的地址偏移量
      valueOffset = unsafe.objectFieldOffset(fieldi);

    } catch (NoSuchFieldException | IllegalAccessException e) {
      e.printStackTrace();
    }
  }

  public void increament() {
    for (; ; ) {
      int current = unsafe.getIntVolatile(this, valueOffset);
      // 如果成功则返回true,跳出循环,如果失败返回false, 将进行自旋(就是for循环)
      if (unsafe.compareAndSwapInt(this, valueOffset, current, current + 1)) break;
    }
  }
}

到此,关于“web线程安全中的原子操作是什么”的学习就结束了,希望能够解决大家的疑惑。理论与实践的搭配能更好的帮助大家学习,快去试试吧!若想继续学习更多相关知识,请继续关注编程笔记网站,小编会继续努力为大家带来更多实用的文章!


推荐阅读
  • 1Lock与ReadWriteLock1.1LockpublicinterfaceLock{voidlock();voidlockInterruptibl ... [详细]
  • HashMap的相关问题及其底层数据结构和操作流程
    本文介绍了关于HashMap的相关问题,包括其底层数据结构、JDK1.7和JDK1.8的差异、红黑树的使用、扩容和树化的条件、退化为链表的情况、索引的计算方法、hashcode和hash()方法的作用、数组容量的选择、Put方法的流程以及并发问题下的操作。文章还提到了扩容死链和数据错乱的问题,并探讨了key的设计要求。对于对Java面试中的HashMap问题感兴趣的读者,本文将为您提供一些有用的技术和经验。 ... [详细]
  • 深入理解Java虚拟机的并发编程与性能优化
    本文主要介绍了Java内存模型与线程的相关概念,探讨了并发编程在服务端应用中的重要性。同时,介绍了Java语言和虚拟机提供的工具,帮助开发人员处理并发方面的问题,提高程序的并发能力和性能优化。文章指出,充分利用计算机处理器的能力和协调线程之间的并发操作是提高服务端程序性能的关键。 ... [详细]
  • 本文介绍了Java高并发程序设计中线程安全的概念与synchronized关键字的使用。通过一个计数器的例子,演示了多线程同时对变量进行累加操作时可能出现的问题。最终值会小于预期的原因是因为两个线程同时对变量进行写入时,其中一个线程的结果会覆盖另一个线程的结果。为了解决这个问题,可以使用synchronized关键字来保证线程安全。 ... [详细]
  • 本文讨论了clone的fork与pthread_create创建线程的不同之处。进程是一个指令执行流及其执行环境,其执行环境是一个系统资源的集合。在调用系统调用fork创建一个进程时,子进程只是完全复制父进程的资源,这样得到的子进程独立于父进程,具有良好的并发性。但是二者之间的通讯需要通过专门的通讯机制,另外通过fork创建子进程系统开销很大。因此,在某些情况下,使用clone或pthread_create创建线程可能更加高效。 ... [详细]
  • 本文介绍了Python爬虫技术基础篇面向对象高级编程(中)中的多重继承概念。通过继承,子类可以扩展父类的功能。文章以动物类层次的设计为例,讨论了按照不同分类方式设计类层次的复杂性和多重继承的优势。最后给出了哺乳动物和鸟类的设计示例,以及能跑、能飞、宠物类和非宠物类的增加对类数量的影响。 ... [详细]
  • 深入理解Kafka服务端请求队列中请求的处理
    本文深入分析了Kafka服务端请求队列中请求的处理过程,详细介绍了请求的封装和放入请求队列的过程,以及处理请求的线程池的创建和容量设置。通过场景分析、图示说明和源码分析,帮助读者更好地理解Kafka服务端的工作原理。 ... [详细]
  • 预备知识可参考我整理的博客Windows编程之线程:https:www.cnblogs.comZhuSenlinp16662075.htmlWindows编程之线程同步:https ... [详细]
  • 重入锁(ReentrantLock)学习及实现原理
    本文介绍了重入锁(ReentrantLock)的学习及实现原理。在学习synchronized的基础上,重入锁提供了更多的灵活性和功能。文章详细介绍了重入锁的特性、使用方法和实现原理,并提供了类图和测试代码供读者参考。重入锁支持重入和公平与非公平两种实现方式,通过对比和分析,读者可以更好地理解和应用重入锁。 ... [详细]
  • 本文介绍了Java集合库的使用方法,包括如何方便地重复使用集合以及下溯造型的应用。通过使用集合库,可以方便地取用各种集合,并将其插入到自己的程序中。为了使集合能够重复使用,Java提供了一种通用类型,即Object类型。通过添加指向集合的对象句柄,可以实现对集合的重复使用。然而,由于集合只能容纳Object类型,当向集合中添加对象句柄时,会丢失其身份或标识信息。为了恢复其本来面貌,可以使用下溯造型。本文还介绍了Java 1.2集合库的特点和优势。 ... [详细]
  • linux进阶50——无锁CAS
    1.概念比较并交换(compareandswap,CAS),是原⼦操作的⼀种,可⽤于在多线程编程中实现不被打断的数据交换操作࿰ ... [详细]
  • 我所理解的JMM 2 new原子性
    概述文本探讨构造函数是否为原子性问题。案例我们首先如下代码:publicclassPerson{publicintage;publicPerson(){age ... [详细]
  • JVM:33 如何查看JVM的Full GC日志
    1.示例代码packagecom.webcode;publicclassDemo4{publicstaticvoidmain(String[]args){byte[]arr ... [详细]
  • Servlet多用户登录时HttpSession会话信息覆盖问题的解决方案
    本文讨论了在Servlet多用户登录时可能出现的HttpSession会话信息覆盖问题,并提供了解决方案。通过分析JSESSIONID的作用机制和编码方式,我们可以得出每个HttpSession对象都是通过客户端发送的唯一JSESSIONID来识别的,因此无需担心会话信息被覆盖的问题。需要注意的是,本文讨论的是多个客户端级别上的多用户登录,而非同一个浏览器级别上的多用户登录。 ... [详细]
  • 本文介绍了一种求解最小权匹配问题的方法,使用了拆点和KM算法。通过将机器拆成多个点,表示加工的顺序,然后使用KM算法求解最小权匹配,得到最优解。文章给出了具体的代码实现,并提供了一篇题解作为参考。 ... [详细]
author-avatar
有海的地方最美_171
这个家伙很懒,什么也没留下!
PHP1.CN | 中国最专业的PHP中文社区 | DevBox开发工具箱 | json解析格式化 |PHP资讯 | PHP教程 | 数据库技术 | 服务器技术 | 前端开发技术 | PHP框架 | 开发工具 | 在线工具
Copyright © 1998 - 2020 PHP1.CN. All Rights Reserved | 京公网安备 11010802041100号 | 京ICP备19059560号-4 | PHP1.CN 第一PHP社区 版权所有