线程安全

Go语言入门(八)线程安全&锁

寵の児 提交于 2020-04-01 11:50:37
线程安全&锁 定时器&一次性定时器 定时器 func main() { ticker := time.NewTicker(time.Second) //ticker.C是一个只读的chan,所以直接可以使用for range读取 for v := range ticker.C { fmt.Printf("hello %v\n",v) //按秒输出 } } 一次性定时器 func main() { select { case <- time.After(time.Second): fmt.Printf("after\n") } } 超时控制 func queryDb(ch chan int) { //模拟DB查询 time.Sleep(time.Second) //模拟查询1秒 ch <- 100 } func main() { ch := make(chan int) go queryDb(ch) //异步查询 t := time.NewTicker(time.Second*3) //定时3秒 select { case v:= <- ch: fmt.Printf("result:%v\n",v) // case <- t.C: fmt.Printf("timeout\n") } } 异常处理: 记录异常,不至于进程被panic等问题 func main() { go func()

java集合--collection集合

寵の児 提交于 2020-03-31 06:40:17
1、画出collection的框架图   集合主要包含collection和map两个接口。其中collection中的元素是一个value值,map中的元素是key:value形式的。   collection包含set、list、queue。     (1)list:list接口包含ArrayList,Vector,LinkedList。     (2)set包含HashSet,TreeSet,EnumSet。     (3)Queueu包含LinkedList,PriorityQueue   map包含HashMap,HashTable,TreeMap,WeakHashMap,IdentityHashMap,EnumMap 2、详述List、Map、Set的区别?(底层实现的数据结构不同)   (1)List:有序,可重复。     ArrayList:底层实现的数据结构是数组,查询快,增删慢。线程不安全,效率高     LinkedList:底层实现的数据结构是链表,查询慢,增删块。线程不安全,效率高     Vector:底层实现的数据结构是数组,查绚块,增删慢。线程安全,效率低。   (2)Set:无序,唯一。     HashSet:底层数据结构是哈希表(无序,唯一)。保证元素唯一性依赖于两个方法:hashCode()和equals()    

07:线程安全-可见性问题

心不动则不痛 提交于 2020-03-30 22:57:40
由指令重排序引起的可见性问题: public class Test { // 如果运行时加上 -server 下面的代码就变成了死循环,没有加就正常运行。(运行器的编译优化只有在服务器模式下才执行) // 通过设置JVM参数,打印出JIT(即时编译)编译的内容(这里说的编译不是指class文件的编译,而是指未变级别的编译) private boolean flag = true; // -server -Djava.compiler=NONE 参数可以关闭jit优化。 // 在多线程中,由于指令重排序引起的线程可见性问题。 public static void main(String[] args) throws IOException, InterruptedException { Test demo1 = new Test(); new Thread(new Runnable() { @Override public void run() { int i = 0; // class文件在运行时jit编译成为汇编指令,汇编指令出现了重排序。 /* // 重排序后的逻辑。因为while语句里面需要一直判断flag。所以jvm优化为外层使用if判断一次。 if(demo1.flag){ while (true){ i++; } } hot code : 热点代码。

Java多线程中static变量的使用

老子叫甜甜 提交于 2020-03-30 11:44:35
线程,是我们项目中绕不过的重点领域。提到线程,就常会听到线程安全的术语。那什么是线程安全呢?通俗点说,就是线程访问时不产生资源冲突。其实,这是一个有点难以定义的概念,不是很容易让人一听就懂的概念。“一个类可以被多个线程安全调用就是线程安全的”《 Java 并发编程实践》。 来说说静态变量、实例变量、局部变量在多线程下的安全问题吧! (一)静态变量:线程非安全 1、静态变量:使用static关键字定义的变量。static可以修饰变量和方法,也有static静态代码块。被static修饰的成员变量和成员方法独立于该类的任何对象。也就是说,它不依赖类特定的实例,被 类的所有实例共享 。只要这个类被加载,Java虚拟机就能根据类名在运行时数据区的方法区内定找到他们。因此,static对象可以在它的任何对象创建之前访问,无需引用任何对象。 用public修饰的static成员变量和成员方法本质是 全局 变量和全局方法,当声明它的类的对象时,不生成static变量的副本,而是类的所有实例共享同一个static变量。 2、静态变量使用的场景: (1)对象间共享值时 (2)方便访问变量时 3、静态方法使用注意事项: (1)不能在静态方法内使用非静态变量,即不能直接访问所属类的实例变量; (2)不能在静态方法内直接调用非静态方法; (3)静态方法中不能使用this和super关键字; 4

java集合对比

南笙酒味 提交于 2020-03-29 20:59:14
list与Set、Map 区别及适用场景 1、List,Set都是继承自Collection接口,Map则不是 2、List特点:元素有放入顺序,元素可重复 ,Set特点:元素无放入顺序,元素不可重复,重复元素会覆盖掉,(注意:元素虽然无放入顺序,但是元素在set中的位置是有该元素的HashCode决定的,其位置其实是固定的,加入Set 的Object必须定义equals()方法 ,另外list支持for循环,也就是通过下标来遍历,也可以用迭代器,但是set只能用迭代,因为他无序,无法用下标来取得想要的值。) 3.Set和List对比: Set:检索元素效率低下,删除和插入效率高,插入和删除不会引起元素位置改变。 List:和数组类似,List可以动态增长,查找元素效率高,插入删除元素效率低,因为会引起其他元素位置改变。 4.Map适合储存键值对的数据 5.线程安全集合类与非线程安全集合类 LinkedList、ArrayList、HashSet是非线程安全的,Vector是线程安全的; HashMap是非线程安全的,HashTable是线程安全的; StringBuilder是非线程安全的,StringBuffer是线程安全的。 下面是具体的使用介绍: ArrayList与LinkedList的区别和适用场景 Arraylist: 优点

Java集合框架面试题目

末鹿安然 提交于 2020-03-29 20:26:32
1.为什么Map接口不继承Collection 接口? Set是无序集合,并且不允许重复的元素 List是有序的集合,并且允许重复的元素 而Map是键值对 它被视为是键的set和值的set的组合 Map被设计为键值对的集合,所以不需要继承Collection 接口 2.HashMap和Hashtable之间的区别? 同步或线程安全 Null键和Null值 迭代值 默认容量大小 3.comparable 和 comparator的不同之处? comparable接口实际上是出自java.lang包 它有一个 compareTo(Object obj)方法来将objects排序 comparator接口实际上是出自 java.util 包 它有一个compare(Object obj1, Object obj2)方法来将objects排序 4.如何对Object的list排序? 对objects数组进行排序,我们可以用Arrays.sort()方法 如果要对objects的集合进行排序,需要使用Collections.sort()方法 5. fail-fast 与 fail-safe 之间的区别? Fail fast快速地报告任何的failure。无论何时任何一个问题都会引发 fail fast系统fails 在Java Fail fast 迭代器中

Java集合类——Set、List、Map、Queue接口

旧街凉风 提交于 2020-03-29 20:23:42
目录 Java 集合类的基本概念 Java 集合类的层次关系 Java 集合类的应用场景 一. Java集合类的基本概念 在编程中,常需要集中存放多个数据,数组是一个很好的选择,但数组的长度需提前指定且不可变,如果我们需要保存一个动态增长的数据(其数量不确定),Java集合类可以很好实现。 集合类又称为容器类。所有的集合类都位于 java.util 包下,为了处理多线程环境下的并发安全问题,在 java.util.concurrent 包下提供了一些多线程支持的集合类。 Java集合类可分为两大类: 1)Collection : 1.1)List必须保持元素特定的顺序 1.2)Set不能有重复元素 1.3)Queue保持一个队列(先进先出)的顺序 2)Map : 保存的是一组 “键值对” 对象 (key-value对) 【虚线箭头表示实现关系,实线箭头表示继承关系】 二. Java集合类的层次关系 1. Iterable<T> 接口 java.lang 下的 Interface Iterable<T> 迭代器接口,是Collecton接口的父接口,包括 default void forEach() 方法 Iterator<T> iterator() 方法 【Iterator<T> 是java.util 下的接口】 实现这个Iterable接口的对象允许使用foreach进行遍历

设计模式之单例模式详解及代码示例

喜你入骨 提交于 2020-03-29 04:20:35
一、什么是单例模式   单例模式的定义就是确保某一个类只有一个实例,并且提供一个全局访问点。属于设计模式三大类中的 创建型模式 。单例模式具有典型的三个特点 单例类只有一个实例对象; 该单例对象必须由单例类自行创建; 单例类对外提供一个访问该单例的全局访问点;   类图如下:                单例模式优缺点 优点 :由于单例模式只生成了一个实例,所以能够节约系统资源,减少性能开销,提高系统效率,同时也能够严格控制客户对它的访问。 缺点 :也正是因为系统中只有一个实例,这样就导致了单例类的职责过重,违背了“单一职责原则”,同时也没有抽象类,这样扩展起来有一定的困难。 二、如何实现单例模式   常见的单例模式实现方式有五种: 饿汉式 、 懒汉式 、 双重检测锁式 、 静态内部类式 和 枚举单例 。而在这五种方式中 饿汉式 和 懒汉式 又最为常见。   1、饿汉式   饿汉式写法是线程安全的,调用效率高。但是不能延时加载。代码如下: public class SingletonDemo1 { //线程安全的 //类初始化时,立即加载这个对象 private static SingletonDemo1 instance = new SingletonDemo1(); private SingletonDemo1() { } //方法没有加同步块,所以它效率高 public

并发编程(6)基于锁的并发数据结构设计

…衆ロ難τιáo~ 提交于 2020-03-29 04:03:42
主要内容: 并发数据结构设计的意义 指导如何设计 实现为并发设计的数据结构   如果一种数据结构可以被多个线程所访问,其要不就是绝对不变的(其值不会发生变化, 并且不需同步),要不程序就要对数据结构进行正确的设计,以确保其能在多线程环境下能够 (正确的)同步。一种选择是使用独立的互斥量,其可以锁住需要保护的数据, 另一种选择是设计一种能够并发访问的数据结构。第一种使用互斥量,在同一时间只有一个线程可以访问数据,实际是一种串行的序列化访问。显示的组织了多线程对数据结构的并发访问。 所以,缩小保护区域,减少序列化访问,就能提高并发。 允许线程并发读取的数据结构并不少见,而对数据结构的修改,必须是单线程独立访问。 所以不可能完全实现并发,只能让序列化访问最小化。 一、基于锁的并发数据结构 基于锁的并发数据结构设计,需要确保访问线程持有锁的时间最短。都是在保证数据结构是线程安全的前提下。在设计数据结构,考虑以下问题: 锁的范围中的操作,是否允许在所外执行? 数据结构中不同的区域是否能被不同的互斥量所保护? 所有操作都需要同级互斥量保护吗? 能否对数据结构进行简单的修改,以增加并发访问的概率,且不影响操作语义? 1、使用锁实现一个线程安全的栈 1 #include <exception> 2 struct empty_stack: std::exception 3 { 4   const

线程安全函数是什么

戏子无情 提交于 2020-03-28 16:41:22
什么是线程安全? 一个函数被多个并发线程 反复调用时,它会一直产生正确的结果 ,则该函数是线程安全函数。 那么什么又是可重入函数? 当一个函数在被一个线程调用时,可以 允许被其他线程再调用 。即两个函数“ 同时 ”发生。则该函数是可重入函数。 所以,显而易见,如果一个函数是可重入的,那么它肯定是线程安全的。但反之未然,一个函数是线程安全的,却未必是可重入的。比如我们在一个函数中调用到了一个全局变量NUM用来标记某一东西的数量。学个操作系统的同学都知道,如果我们在修改它的值的时候发生了中断,两一个函数又对他进行了修改,此时该变量的值会出错。这种函数就是线程不安全函数。他是属于没有保护共享变量的线程不安全函数。在单线程时运行毫无问题,但一旦放到多线程中就容易出bug。但如果我们在修改这个全局变量NUM前对他进行加锁,再操作完后再进行解锁。这样即使有两个线程在调用这个函数,其结果也不会出问题。此时,这个函数就是线程安全函数。但他依旧不是可重入函数。因为他不能保证两个函数“同时”运行,必须等待解锁后才能运行。而我们在平时开发中应该尽量编写可重入的函数。 如下图: 线程不安全函数主要分为以下四大类: 第一类:不保护共享变量的函数, a, 函数中访问全局变量和堆。 共享变量在多线程中是共享数据比如全局变量和堆,如果不保护共享变量,多线程时会出bug。 可以通过同步机制来保护共享数据,比如加锁。