首页
关于
友链
Search
1
wlop 4K 壁纸 4k8k 动态 壁纸
1,468 阅读
2
Nacos持久化MySQL问题-解决方案
932 阅读
3
Docker搭建Typecho博客
752 阅读
4
滑动时间窗口算法
728 阅读
5
Nginx反向代理微服务配置
699 阅读
生活
解决方案
JAVA基础
JVM
多线程
开源框架
数据库
前端
分布式
框架整合
中间件
容器部署
设计模式
数据结构与算法
安全
开发工具
百度网盘
天翼网盘
阿里网盘
登录
Search
标签搜索
java
javase
docker
java8
springboot
thread
spring
分布式
mysql
锁
linux
redis
源码
typecho
centos
git
map
RabbitMQ
lambda
stream
少年
累计撰写
189
篇文章
累计收到
24
条评论
首页
栏目
生活
解决方案
JAVA基础
JVM
多线程
开源框架
数据库
前端
分布式
框架整合
中间件
容器部署
设计模式
数据结构与算法
安全
开发工具
百度网盘
天翼网盘
阿里网盘
页面
关于
友链
搜索到
5
篇与
的结果
2022-04-24
线程安全-同步容器
线程安全-同步容器主要包括ArrayList -> Vector,Stack HashMap->HashTable(key、value不能为null)Collections.synchronizedXXX(List、Set、Map)都是使用Synchronized进行修饰的,性能不是特别好。可以使用并发容器代替。注意:同步容器也可能是线程步安全的。同步容器线程步安全,代码示例:package com.yanxizhu.demo.concurrency.synContainer; import com.yanxizhu.demo.concurrency.annotation.UnThreadSafety; import java.util.Vector; /** * @description: 同步容器,也可能出现线程不安全情况 * @author: <a href="mailto:vip@foxmail.com">清风</a> * @date: 2022/4/24 10:32 * @version: 1.0 */ @UnThreadSafety public class DemoVecotNo { private static final Vector<Integer> vector = new Vector<>(); public static void main(String[] args) { //一直循环 while(true) { //向vector容器放入值 for(int i=0; i <10; i++){ vector.add(i); } //线程1,向vector容器移除值 new Thread(()->{ for(int i=0; i <vector.size(); i++){ vector.remove(i); } }).start(); //线程2,向vector中获取值 new Thread(()->{ for(int i=0; i <vector.size(); i++){ vector.get(i); } }).start(); } } }输出结果:Exception in thread "Thread-478" Exception in thread "Thread-1724" Exception in thread "Thread-1918" Exception in thread "Thread-1769" java.lang.ArrayIndexOutOfBoundsException: Array index out of range: 10 at java.base/java.util.Vector.remove(Vector.java:875) at com.yanxizhu.demo.concurrency.synContainer.DemoVecotNo.lambda$main$0(DemoVecotNo.java:27) at java.base/java.lang.Thread.run(Thread.java:834) java.lang.ArrayIndexOutOfBoundsException: Array index out of range: 62 at java.base/java.util.Vector.remove(Vector.java:875) at com.yanxizhu.demo.concurrency.synContainer.DemoVecotNo.lambda$main$0(DemoVecotNo.java:27) at java.base/java.lang.Thread.run(Thread.java:834) java.lang.ArrayIndexOutOfBoundsException: Array index out of range: 2 at java.base/java.util.Vector.get(Vector.java:781) at com.yanxizhu.demo.concurrency.synContainer.DemoVecotNo.lambda$main$1(DemoVecotNo.java:34) at java.base/java.lang.Thread.run(Thread.java:834) java.lang.ArrayIndexOutOfBoundsException: Array index out of range: 10 at java.base/java.util.Vector.remove(Vector.java:875) at com.yanxizhu.demo.concurrency.synContainer.DemoVecotNo.lambda$main$0(DemoVecotNo.java:27) at java.base/java.lang.Thread.run(Thread.java:834) Exception in thread "Thread-4507" java.lang.ArrayIndexOutOfBoundsException: Array index out of range: 12 at java.base/java.util.Vector.get(Vector.java:781) at com.yanxizhu.demo.concurrency.synContainer.DemoVecotNo.lambda$main$1(DemoVecotNo.java:34) at java.base/java.lang.Thread.run(Thread.java:834)说明:add、remove、get防范都是通过synchronized修饰了的,为什么还是会出现线程不安全,因为当remove和get运行时,如果i相等,remove移除i时,get再获取i就包错了。Vector线程安全代码示例package com.yanxizhu.demo.concurrency.synContainer; import com.yanxizhu.demo.concurrency.annotation.ThreadSafety; import lombok.extern.slf4j.Slf4j; import java.util.Vector; import java.util.concurrent.CountDownLatch; import java.util.concurrent.ExecutorService; import java.util.concurrent.Executors; import java.util.concurrent.Semaphore; /** * @description: 线程安全容器:Vector * @author: <a href="mailto:vip@foxmail.com">清风</a> * @date: 2022/4/24 10:18 * @version: 1.0 */ @Slf4j @ThreadSafety public class DeomVecotr { private static Vector<Integer> vector = new Vector<>(); //用户数量 private static final int clientsTotal = 5000; //并发数量 private static final int concurrencyTotal = 200; public static void main(String[] args) throws InterruptedException { ExecutorService executorService = Executors.newCachedThreadPool(); //信号量 final Semaphore semaphore = new Semaphore(concurrencyTotal); //闭锁 final CountDownLatch countDownLatch = new CountDownLatch(clientsTotal); for (int i = 0; i < clientsTotal; i++) { final int count = i; executorService.execute(()->{ try { semaphore.acquire(); update(count); semaphore.release(); } catch (InterruptedException e) { log.error("出现错误:【{}】", e.getMessage()); } countDownLatch.countDown(); }); } countDownLatch.await(); executorService.shutdown(); log.info("vector size:{}", vector.size()); } /** * 通过线程安全对象dateTimeFormatter处理 */ private static void update(int count){ vector.add(count); } }输出结果:每次是输出5000Hashtable线程安全,代码示例:package com.yanxizhu.demo.concurrency.synContainer; import com.yanxizhu.demo.concurrency.annotation.ThreadSafety; import com.yanxizhu.demo.concurrency.annotation.UnThreadSafety; import lombok.extern.slf4j.Slf4j; import java.util.HashMap; import java.util.Hashtable; import java.util.Map; import java.util.concurrent.CountDownLatch; import java.util.concurrent.ExecutorService; import java.util.concurrent.Executors; import java.util.concurrent.Semaphore; /** * @description: 线程安全容器:Hashtable * @author: <a href="mailto:vip@foxmail.com">清风</a> * @date: 2022/4/24 9:52 * @version: 1.0 */ @Slf4j @ThreadSafety public class DemoHashTable { private static Map<Integer, Integer> map = new Hashtable<>(); //用户数量 private static final int clientsTotal = 5000; //并发数量 private static final int concurrencyTotal = 200; public static void main(String[] args) throws InterruptedException { ExecutorService executorService = Executors.newCachedThreadPool(); //信号量 final Semaphore semaphore = new Semaphore(concurrencyTotal); //闭锁 final CountDownLatch countDownLatch = new CountDownLatch(clientsTotal); for (int i = 0; i < clientsTotal; i++) { final int count = i; executorService.execute(()->{ try { semaphore.acquire(); update(count); semaphore.release(); } catch (InterruptedException e) { log.error("出现错误:【{}】", e.getMessage()); } countDownLatch.countDown(); }); } countDownLatch.await(); executorService.shutdown(); log.info("map size:{}", map.size()); } private static void update(int count){ map.put(count, count); } }输出结果:每次都是5000.线程安全。Collections.synchronizedList线程安全,同步容器package com.yanxizhu.demo.concurrency.synContainer; import com.yanxizhu.demo.concurrency.annotation.ThreadSafety; import lombok.extern.slf4j.Slf4j; import java.util.ArrayList; import java.util.Collections; import java.util.List; import java.util.concurrent.CountDownLatch; import java.util.concurrent.ExecutorService; import java.util.concurrent.Executors; import java.util.concurrent.Semaphore; /** * @description: 安全容器,Collections下的同步容器,线程安全 * @author: <a href="mailto:vip@foxmail.com">清风</a> * @date: 2022/4/24 10:47 * @version: 1.0 */ @Slf4j @ThreadSafety public class DemoCollections { private static List<Integer> list = Collections.synchronizedList(new ArrayList<>()); //用户数量 private static final int clientsTotal = 5000; //并发数量 private static final int concurrencyTotal = 200; public static void main(String[] args) throws InterruptedException { ExecutorService executorService = Executors.newCachedThreadPool(); //信号量 final Semaphore semaphore = new Semaphore(concurrencyTotal); //闭锁 final CountDownLatch countDownLatch = new CountDownLatch(clientsTotal); for (int i = 0; i < clientsTotal; i++) { final int count = i; executorService.execute(()->{ try { semaphore.acquire(); update(count); semaphore.release(); } catch (InterruptedException e) { log.error("出现错误:【{}】", e.getMessage()); } countDownLatch.countDown(); }); } countDownLatch.await(); executorService.shutdown(); log.info("list size:{}", list.size()); } /** * 通过线程安全对象dateTimeFormatter处理 */ private static void update(int count){ list.add(count); } }输出结果:每次输出5000,线程安全。Collections.synchronizedSet线程安全,同步容器,代码示例package com.yanxizhu.demo.concurrency.synContainer; import com.google.common.collect.Sets; import com.yanxizhu.demo.concurrency.annotation.ThreadSafety; import lombok.extern.slf4j.Slf4j; import java.util.Collections; import java.util.Set; import java.util.concurrent.CountDownLatch; import java.util.concurrent.ExecutorService; import java.util.concurrent.Executors; import java.util.concurrent.Semaphore; /** * @description: 安全容器,Collections下的同步容器,synchronizedSet,线程安全 * @author: <a href="mailto:vip@foxmail.com">清风</a> * @date: 2022/4/24 10:47 * @version: 1.0 */ @Slf4j @ThreadSafety public class DemoCollectionsSynSet { private static Set<Integer> set = Collections.synchronizedSet(Sets.newHashSet()); //用户数量 private static final int clientsTotal = 5000; //并发数量 private static final int concurrencyTotal = 200; public static void main(String[] args) throws InterruptedException { ExecutorService executorService = Executors.newCachedThreadPool(); //信号量 final Semaphore semaphore = new Semaphore(concurrencyTotal); //闭锁 final CountDownLatch countDownLatch = new CountDownLatch(clientsTotal); for (int i = 0; i < clientsTotal; i++) { final int count = i; executorService.execute(()->{ try { semaphore.acquire(); update(count); semaphore.release(); } catch (InterruptedException e) { log.error("出现错误:【{}】", e.getMessage()); } countDownLatch.countDown(); }); } countDownLatch.await(); executorService.shutdown(); log.info("set size:{}", set.size()); } /** * 通过线程安全对象dateTimeFormatter处理 */ private static void update(int count){ set.add(count); } }输出结果:每次输出5000,线程安全Collections.synchronizedMap线程安全同步容器,代码示例:package com.yanxizhu.demo.concurrency.synContainer; import com.yanxizhu.demo.concurrency.annotation.UnThreadSafety; import lombok.extern.slf4j.Slf4j; import java.util.Collections; import java.util.HashMap; import java.util.Map; import java.util.concurrent.CountDownLatch; import java.util.concurrent.ExecutorService; import java.util.concurrent.Executors; import java.util.concurrent.Semaphore; /** * @description: 安全容器,Collections.synchronizedMap,线程安全 * @author: <a href="mailto:vip@foxmail.com">清风</a> * @date: 2022/4/24 9:52 * @version: 1.0 */ @Slf4j @UnThreadSafety public class DemoCollectionsSynHashMap { private static Map<Integer, Integer> map = Collections.synchronizedMap(new HashMap()); //用户数量 private static final int clientsTotal = 5000; //并发数量 private static final int concurrencyTotal = 200; public static void main(String[] args) throws InterruptedException { ExecutorService executorService = Executors.newCachedThreadPool(); //信号量 final Semaphore semaphore = new Semaphore(concurrencyTotal); //闭锁 final CountDownLatch countDownLatch = new CountDownLatch(clientsTotal); for (int i = 0; i < clientsTotal; i++) { final int count = i; executorService.execute(()->{ try { semaphore.acquire(); update(count); semaphore.release(); } catch (InterruptedException e) { log.error("出现错误:【{}】", e.getMessage()); } countDownLatch.countDown(); }); } countDownLatch.await(); executorService.shutdown(); log.info("map size:{}", map.size()); } private static void update(int count){ map.put(count, count); } }输出结果:每次输出5000,线程安全。常用操作错误package com.yanxizhu.demo.concurrency.synContainer; import java.util.Iterator; import java.util.Vector; /** * @description: 常见容器使用错误,解决办法 * @author: <a href="mailto:vip@foxmail.com">清风</a> * @date: 2022/4/24 11:04 * @version: 1.0 */ public class DemoErrorUser { //增强for循环中修改,报错:java.util.ConcurrentModificationException public static void test1(Vector<Integer> vector) { for (Integer integer: vector) { //使用增强for循环 if (integer.equals(3)) { // vector.remove(integer); vector.add(4); } } } //迭代器中循环修改,报错:java.util.ConcurrentModificationException public static void test2(Vector<Integer> vector) { Iterator<Integer> iterator = vector.iterator(); while (iterator.hasNext()){ Integer integer = iterator.next(); if( integer.equals(3)) { vector.remove(integer); } } } //普通for循环中修改,正常。 public static void test3(Vector<Integer> vector) { for(int i=0; i< vector.size(); i++) { if(i==3) { vector.remove(i); } } } //总结:增强for、迭代器循环中修改,可以先标记,然后最后进行修改。 public static void main(String[] args) { Vector<Integer> vector = new Vector<>(); vector.add(1); vector.add(2); vector.add(3); test1(vector); // test2(vector); // test3(vector); } }输出结果:ConcurrentModificationExceptionException in thread "main" java.util.ConcurrentModificationException at java.base/java.util.Vector$Itr.checkForComodification(Vector.java:1321) at java.base/java.util.Vector$Itr.next(Vector.java:1277) at com.yanxizhu.demo.concurrency.synContainer.DemoErrorUser.test1(DemoErrorUser.java:16) at com.yanxizhu.demo.concurrency.synContainer.DemoErrorUser.main(DemoErrorUser.java:52)增强for、迭代器中循环修改线程报错,正常for循环,正常,解决办法,通过标记后,再单独进行移除操作。
2022年04月24日
213 阅读
0 评论
2 点赞
2022-04-21
Synchronized
Atomic原子性提供了互斥访问。同一时刻只能由一个线程来操作。除了Atomic原子性,还有锁。jdk提供的锁主要分2类1、Synchronized:一种依赖JVM去实现锁的关键字,Synchronized,在这个对象作用的范围内,都是同一时刻,只能有一个线程去操作。注意是,作用对象的作用范围内。2、另一种jdk代码层面的锁,jdk里面提供了一个Lock的接口,主要是依赖特殊的CPU指令,实现类中比较有代表性的是ReentrantLock。Synchronized一种同步锁,修改的对象主要有4种:修饰代码块:大括号括起来的代码,也就是同步语句块,它的作用范围是大括号括起来的代码,作用对象是调用代码块的对象。修饰方法:被称为同步方法,作用范围为整个方法,作用对象是也是调用该方法的对象。修饰静态方法:作用范围整个静态方法,作用对象是这个类的所有对象。修饰类:修饰内容是后面Synchronized括号括起来的部分,作用对象也是这个类的所有对象。代码说明:一、启用不同进程,同一对象调用,调用同一方法。package com.yanxizhu.demo.concurrency.sync; import lombok.extern.slf4j.Slf4j; import java.util.concurrent.ExecutorService; import java.util.concurrent.Executors; /** * @description: Synchronized修饰代码块、修改方法,作用对象为调用对象 * 这里测试,同一对象,启动不同进程,调同一方法 * @author: <a href="mailto:batis@foxmail.com">清风</a> * @date: 2022/4/20 22:44 * @version: 1.0 */ @Slf4j public class DemoSynchronizedOne { /** * 修饰代码块,大括号被称为 同步代码块, * 作用范围:代码块内 * 作用对象:调用代码块的对象 */ public void test1() { synchronized (this) { for (int i = 0; i < 10 ;i ++){ log.info("test1 ...i={}",i); } } } /** * 修饰方法,该方法被称为同步方 * 作为范围:整个test2方法 * 作用对象:调用代码块的对象 */ public synchronized void test2() { for (int i = 0; i < 10 ;i ++){ log.info("test2 ...i={}",i); } } public static void main(String[] args) { DemoSynchronizedOne demoSynchronized = new DemoSynchronizedOne(); //线程池 ExecutorService executorService = Executors.newCachedThreadPool(); /** * 说明: 为什么执行2次 * 如果不用线程池,下面2次调用都是同一线程,不能验证。 * 使用线程池,相当于用了2各进程去执行test1,不用等一个进程执行完,在执行第二个线程, * 这样才能看到同一个对象的不同进程的执行情况。 */ //-----------------------------------测试同一对象的方法test1------------------------------------------- // 测试1: executorService.execute(() -> { demoSynchronized.test1(); }); executorService.execute(() -> { demoSynchronized.test1(); }); /* 输出结果: 23:33:52.670 [pool-1-thread-1] INFO com.yanxizhu.demo.concurrency.sync.DemoSynchronizedOne - test1 ...i=0 23:33:52.674 [pool-1-thread-1] INFO com.yanxizhu.demo.concurrency.sync.DemoSynchronizedOne - test1 ...i=1 23:33:52.674 [pool-1-thread-1] INFO com.yanxizhu.demo.concurrency.sync.DemoSynchronizedOne - test1 ...i=2 23:33:52.674 [pool-1-thread-1] INFO com.yanxizhu.demo.concurrency.sync.DemoSynchronizedOne - test1 ...i=3 23:33:52.674 [pool-1-thread-1] INFO com.yanxizhu.demo.concurrency.sync.DemoSynchronizedOne - test1 ...i=4 23:33:52.674 [pool-1-thread-1] INFO com.yanxizhu.demo.concurrency.sync.DemoSynchronizedOne - test1 ...i=5 23:33:52.674 [pool-1-thread-1] INFO com.yanxizhu.demo.concurrency.sync.DemoSynchronizedOne - test1 ...i=6 23:33:52.674 [pool-1-thread-1] INFO com.yanxizhu.demo.concurrency.sync.DemoSynchronizedOne - test1 ...i=7 23:33:52.674 [pool-1-thread-1] INFO com.yanxizhu.demo.concurrency.sync.DemoSynchronizedOne - test1 ...i=8 23:33:52.674 [pool-1-thread-1] INFO com.yanxizhu.demo.concurrency.sync.DemoSynchronizedOne - test1 ...i=9 23:33:52.674 [pool-1-thread-2] INFO com.yanxizhu.demo.concurrency.sync.DemoSynchronizedOne - test1 ...i=0 23:33:52.675 [pool-1-thread-2] INFO com.yanxizhu.demo.concurrency.sync.DemoSynchronizedOne - test1 ...i=1 23:33:52.675 [pool-1-thread-2] INFO com.yanxizhu.demo.concurrency.sync.DemoSynchronizedOne - test1 ...i=2 23:33:52.675 [pool-1-thread-2] INFO com.yanxizhu.demo.concurrency.sync.DemoSynchronizedOne - test1 ...i=3 23:33:52.675 [pool-1-thread-2] INFO com.yanxizhu.demo.concurrency.sync.DemoSynchronizedOne - test1 ...i=4 23:33:52.675 [pool-1-thread-2] INFO com.yanxizhu.demo.concurrency.sync.DemoSynchronizedOne - test1 ...i=5 23:33:52.675 [pool-1-thread-2] INFO com.yanxizhu.demo.concurrency.sync.DemoSynchronizedOne - test1 ...i=6 23:33:52.675 [pool-1-thread-2] INFO com.yanxizhu.demo.concurrency.sync.DemoSynchronizedOne - test1 ...i=7 23:33:52.675 [pool-1-thread-2] INFO com.yanxizhu.demo.concurrency.sync.DemoSynchronizedOne - test1 ...i=8 23:33:52.675 [pool-1-thread-2] INFO com.yanxizhu.demo.concurrency.sync.DemoSynchronizedOne - test1 ...i=9*/ //-----------------------------------测试同一对象的方法test2------------------------------------------- // 测试2: executorService.execute(() -> { demoSynchronized.test2(); }); executorService.execute(() -> { demoSynchronized.test2(); }); /* 输出结果: 23:33:24.291 [pool-1-thread-1] INFO com.yanxizhu.demo.concurrency.sync.DemoSynchronizedOne - test2 ...i=0 23:33:24.295 [pool-1-thread-1] INFO com.yanxizhu.demo.concurrency.sync.DemoSynchronizedOne - test2 ...i=1 23:33:24.296 [pool-1-thread-1] INFO com.yanxizhu.demo.concurrency.sync.DemoSynchronizedOne - test2 ...i=2 23:33:24.296 [pool-1-thread-1] INFO com.yanxizhu.demo.concurrency.sync.DemoSynchronizedOne - test2 ...i=3 23:33:24.296 [pool-1-thread-1] INFO com.yanxizhu.demo.concurrency.sync.DemoSynchronizedOne - test2 ...i=4 23:33:24.296 [pool-1-thread-1] INFO com.yanxizhu.demo.concurrency.sync.DemoSynchronizedOne - test2 ...i=5 23:33:24.296 [pool-1-thread-1] INFO com.yanxizhu.demo.concurrency.sync.DemoSynchronizedOne - test2 ...i=6 23:33:24.296 [pool-1-thread-1] INFO com.yanxizhu.demo.concurrency.sync.DemoSynchronizedOne - test2 ...i=7 23:33:24.296 [pool-1-thread-1] INFO com.yanxizhu.demo.concurrency.sync.DemoSynchronizedOne - test2 ...i=8 23:33:24.296 [pool-1-thread-1] INFO com.yanxizhu.demo.concurrency.sync.DemoSynchronizedOne - test2 ...i=9 23:33:24.296 [pool-1-thread-2] INFO com.yanxizhu.demo.concurrency.sync.DemoSynchronizedOne - test2 ...i=0 23:33:24.296 [pool-1-thread-2] INFO com.yanxizhu.demo.concurrency.sync.DemoSynchronizedOne - test2 ...i=1 23:33:24.296 [pool-1-thread-2] INFO com.yanxizhu.demo.concurrency.sync.DemoSynchronizedOne - test2 ...i=2 23:33:24.296 [pool-1-thread-2] INFO com.yanxizhu.demo.concurrency.sync.DemoSynchronizedOne - test2 ...i=3 23:33:24.296 [pool-1-thread-2] INFO com.yanxizhu.demo.concurrency.sync.DemoSynchronizedOne - test2 ...i=4 23:33:24.296 [pool-1-thread-2] INFO com.yanxizhu.demo.concurrency.sync.DemoSynchronizedOne - test2 ...i=5 23:33:24.296 [pool-1-thread-2] INFO com.yanxizhu.demo.concurrency.sync.DemoSynchronizedOne - test2 ...i=6 23:33:24.296 [pool-1-thread-2] INFO com.yanxizhu.demo.concurrency.sync.DemoSynchronizedOne - test2 ...i=7 23:33:24.296 [pool-1-thread-2] INFO com.yanxizhu.demo.concurrency.sync.DemoSynchronizedOne - test2 ...i=8 23:33:24.296 [pool-1-thread-2] INFO com.yanxizhu.demo.concurrency.sync.DemoSynchronizedOne - test2 ...i=9*/ executorService.shutdown(); } }二、启动不同进程,不同对象,调用同一方法package com.yanxizhu.demo.concurrency.sync; import lombok.extern.slf4j.Slf4j; import java.util.concurrent.ExecutorService; import java.util.concurrent.Executors; /** * * @description: Synchronized修饰代码块、修改方法,作用对象为调用对象 * 这里测试,不同对象,启动不同进程,调同一方法 * @author: <a href="mailto:batis@foxmail.com">清风</a> * @date: 2022/4/20 22:44 * @version: 1.0 */ @Slf4j public class DemoSynchronizedTwo { /** * 修饰代码块,大括号被称为 同步代码块, * 作用范围:代码块内 * 作用对象:调用代码块的对象 */ public void test1(int j) { synchronized (this) { for (int i = 0; i < 10 ;i ++){ log.info("test1 ...i={},j={}",i,j); } } } /** * 修饰方法,该方法被称为同步方 * 作为范围:整个test2方法 * 作用对象:调用代码块的对象 */ public synchronized void test2(int j) { for (int i = 0; i < 10 ;i ++){ log.info("test2 ...i={},j={}",i,j); } } public static void main(String[] args) { DemoSynchronizedTwo demoSynchronizedTwo = new DemoSynchronizedTwo(); DemoSynchronizedTwo demoSynchronizedTwo2 = new DemoSynchronizedTwo(); //线程池 ExecutorService executorService = Executors.newCachedThreadPool(); //-----------------------------------测试同一对象的方法test1,作用代码块------------------------------------------- // executorService.execute(()->{ // demoSynchronizedTwo.test1(1); // demoSynchronizedTwo2.test1(2); // }); /* 输出结果: 23:28:57.763 [pool-1-thread-1] INFO com.yanxizhu.demo.concurrency.sync.DemoSynchronizedTwo - test1 ...i=0,j=1 23:28:57.768 [pool-1-thread-1] INFO com.yanxizhu.demo.concurrency.sync.DemoSynchronizedTwo - test1 ...i=1,j=1 23:28:57.768 [pool-1-thread-1] INFO com.yanxizhu.demo.concurrency.sync.DemoSynchronizedTwo - test1 ...i=2,j=1 23:28:57.768 [pool-1-thread-1] INFO com.yanxizhu.demo.concurrency.sync.DemoSynchronizedTwo - test1 ...i=3,j=1 23:28:57.768 [pool-1-thread-1] INFO com.yanxizhu.demo.concurrency.sync.DemoSynchronizedTwo - test1 ...i=4,j=1 23:28:57.768 [pool-1-thread-1] INFO com.yanxizhu.demo.concurrency.sync.DemoSynchronizedTwo - test1 ...i=5,j=1 23:28:57.768 [pool-1-thread-1] INFO com.yanxizhu.demo.concurrency.sync.DemoSynchronizedTwo - test1 ...i=6,j=1 23:28:57.769 [pool-1-thread-1] INFO com.yanxizhu.demo.concurrency.sync.DemoSynchronizedTwo - test1 ...i=7,j=1 23:28:57.769 [pool-1-thread-1] INFO com.yanxizhu.demo.concurrency.sync.DemoSynchronizedTwo - test1 ...i=8,j=1 23:28:57.769 [pool-1-thread-1] INFO com.yanxizhu.demo.concurrency.sync.DemoSynchronizedTwo - test1 ...i=9,j=1 23:28:57.769 [pool-1-thread-1] INFO com.yanxizhu.demo.concurrency.sync.DemoSynchronizedTwo - test1 ...i=0,j=2 23:28:57.769 [pool-1-thread-1] INFO com.yanxizhu.demo.concurrency.sync.DemoSynchronizedTwo - test1 ...i=1,j=2 23:28:57.769 [pool-1-thread-1] INFO com.yanxizhu.demo.concurrency.sync.DemoSynchronizedTwo - test1 ...i=2,j=2 23:28:57.769 [pool-1-thread-1] INFO com.yanxizhu.demo.concurrency.sync.DemoSynchronizedTwo - test1 ...i=3,j=2 23:28:57.769 [pool-1-thread-1] INFO com.yanxizhu.demo.concurrency.sync.DemoSynchronizedTwo - test1 ...i=4,j=2 23:28:57.769 [pool-1-thread-1] INFO com.yanxizhu.demo.concurrency.sync.DemoSynchronizedTwo - test1 ...i=5,j=2 23:28:57.769 [pool-1-thread-1] INFO com.yanxizhu.demo.concurrency.sync.DemoSynchronizedTwo - test1 ...i=6,j=2 23:28:57.769 [pool-1-thread-1] INFO com.yanxizhu.demo.concurrency.sync.DemoSynchronizedTwo - test1 ...i=7,j=2 23:28:57.769 [pool-1-thread-1] INFO com.yanxizhu.demo.concurrency.sync.DemoSynchronizedTwo - test1 ...i=8,j=2 23:28:57.769 [pool-1-thread-1] INFO com.yanxizhu.demo.concurrency.sync.DemoSynchronizedTwo - test1 ...i=9,j=2*/ /* * 结论:说明作用于同步代码,不同对象的调用是相互不影响的 * */ //-----------------------------------测试同一对象的方法test2,作用方法------------------------------------------- executorService.execute(()->{ demoSynchronizedTwo.test2(1); demoSynchronizedTwo2.test2(2); }); /* 输出结果: 23:34:56.130 [pool-1-thread-1] INFO com.yanxizhu.demo.concurrency.sync.DemoSynchronizedTwo - test2 ...i=0,j=1 23:34:56.135 [pool-1-thread-1] INFO com.yanxizhu.demo.concurrency.sync.DemoSynchronizedTwo - test2 ...i=1,j=1 23:34:56.135 [pool-1-thread-1] INFO com.yanxizhu.demo.concurrency.sync.DemoSynchronizedTwo - test2 ...i=2,j=1 23:34:56.135 [pool-1-thread-1] INFO com.yanxizhu.demo.concurrency.sync.DemoSynchronizedTwo - test2 ...i=3,j=1 23:34:56.135 [pool-1-thread-1] INFO com.yanxizhu.demo.concurrency.sync.DemoSynchronizedTwo - test2 ...i=4,j=1 23:34:56.135 [pool-1-thread-1] INFO com.yanxizhu.demo.concurrency.sync.DemoSynchronizedTwo - test2 ...i=5,j=1 23:34:56.135 [pool-1-thread-1] INFO com.yanxizhu.demo.concurrency.sync.DemoSynchronizedTwo - test2 ...i=6,j=1 23:34:56.135 [pool-1-thread-1] INFO com.yanxizhu.demo.concurrency.sync.DemoSynchronizedTwo - test2 ...i=7,j=1 23:34:56.135 [pool-1-thread-1] INFO com.yanxizhu.demo.concurrency.sync.DemoSynchronizedTwo - test2 ...i=8,j=1 23:34:56.135 [pool-1-thread-1] INFO com.yanxizhu.demo.concurrency.sync.DemoSynchronizedTwo - test2 ...i=9,j=1 23:34:56.135 [pool-1-thread-1] INFO com.yanxizhu.demo.concurrency.sync.DemoSynchronizedTwo - test2 ...i=0,j=2 23:34:56.135 [pool-1-thread-1] INFO com.yanxizhu.demo.concurrency.sync.DemoSynchronizedTwo - test2 ...i=1,j=2 23:34:56.135 [pool-1-thread-1] INFO com.yanxizhu.demo.concurrency.sync.DemoSynchronizedTwo - test2 ...i=2,j=2 23:34:56.135 [pool-1-thread-1] INFO com.yanxizhu.demo.concurrency.sync.DemoSynchronizedTwo - test2 ...i=3,j=2 23:34:56.135 [pool-1-thread-1] INFO com.yanxizhu.demo.concurrency.sync.DemoSynchronizedTwo - test2 ...i=4,j=2 23:34:56.135 [pool-1-thread-1] INFO com.yanxizhu.demo.concurrency.sync.DemoSynchronizedTwo - test2 ...i=5,j=2 23:34:56.135 [pool-1-thread-1] INFO com.yanxizhu.demo.concurrency.sync.DemoSynchronizedTwo - test2 ...i=6,j=2 23:34:56.135 [pool-1-thread-1] INFO com.yanxizhu.demo.concurrency.sync.DemoSynchronizedTwo - test2 ...i=7,j=2 23:34:56.135 [pool-1-thread-1] INFO com.yanxizhu.demo.concurrency.sync.DemoSynchronizedTwo - test2 ...i=8,j=2 23:34:56.135 [pool-1-thread-1] INFO com.yanxizhu.demo.concurrency.sync.DemoSynchronizedTwo - test2 ...i=9,j=2*/ /* * 结论:说明作用于方法,不同对象的调用是相互不影响的 * */ executorService.shutdown(); } }1和2对别结论:修饰带块和修改方法对别结论1、当一个方法内都是用同步代码块修饰的,和修饰方法是一样的。例如上面的: public void test1(int j) { synchronized (this) { for (int i = 0; i < 10 ;i ++){ log.info("test1 ...i={},j={}",i,j); } } } 等同与下面的修饰方法: public synchronized void test2(int j) { for (int i = 0; i < 10 ;i ++){ log.info("test2 ...i={},j={}",i,j); } }2、修饰静态代码块和修饰方法,作用对象都是调用对象。3、如果某个子类继承了上面的类,子类种test2方法是不带synchronized关键字的,因为synchronized不输入方法申明的一部分,如果子类想使用,则需要显示自己加synchronized。三、不同对象调用同一方法,synchronized修改类和方法:package com.yanxizhu.demo.concurrency.sync; import lombok.extern.slf4j.Slf4j; import java.util.concurrent.ExecutorService; import java.util.concurrent.Executors; /** * * @description: Synchronized修饰静态方法、类 * @author: <a href="mailto:batis@foxmail.com">清风</a> * @date: 2022/4/20 22:44 * @version: 1.0 */ @Slf4j public class DemoSynchronizedThredd { //修饰类 public static void test1(int j) { synchronized (DemoSynchronizedThredd.class) { for (int i = 0; i < 10 ;i ++){ log.info("test1 ...i={},j={}",i,j); } } } //修饰静态方法 public static synchronized void test2(int j) { for (int i = 0; i < 10 ;i ++){ log.info("test2 ...i={},j={}",i,j); } } public static void main(String[] args) { DemoSynchronizedThredd demoSynchronizedTwo = new DemoSynchronizedThredd(); DemoSynchronizedThredd demoSynchronizedTwo2 = new DemoSynchronizedThredd(); //线程池 ExecutorService executorService = Executors.newCachedThreadPool(); //-----------------------------------测试同一对象的方法test1,作用代码块------------------------------------------- executorService.execute(()->{ demoSynchronizedTwo.test1(1); demoSynchronizedTwo2.test1(2); }); /* 输出结果: 23:49:32.176 [pool-1-thread-1] INFO com.yanxizhu.demo.concurrency.sync.DemoSynchronizedThredd - test1 ...i=0,j=1 23:49:32.181 [pool-1-thread-1] INFO com.yanxizhu.demo.concurrency.sync.DemoSynchronizedThredd - test1 ...i=1,j=1 23:49:32.181 [pool-1-thread-1] INFO com.yanxizhu.demo.concurrency.sync.DemoSynchronizedThredd - test1 ...i=2,j=1 23:49:32.181 [pool-1-thread-1] INFO com.yanxizhu.demo.concurrency.sync.DemoSynchronizedThredd - test1 ...i=3,j=1 23:49:32.181 [pool-1-thread-1] INFO com.yanxizhu.demo.concurrency.sync.DemoSynchronizedThredd - test1 ...i=4,j=1 23:49:32.181 [pool-1-thread-1] INFO com.yanxizhu.demo.concurrency.sync.DemoSynchronizedThredd - test1 ...i=5,j=1 23:49:32.181 [pool-1-thread-1] INFO com.yanxizhu.demo.concurrency.sync.DemoSynchronizedThredd - test1 ...i=6,j=1 23:49:32.181 [pool-1-thread-1] INFO com.yanxizhu.demo.concurrency.sync.DemoSynchronizedThredd - test1 ...i=7,j=1 23:49:32.181 [pool-1-thread-1] INFO com.yanxizhu.demo.concurrency.sync.DemoSynchronizedThredd - test1 ...i=8,j=1 23:49:32.181 [pool-1-thread-1] INFO com.yanxizhu.demo.concurrency.sync.DemoSynchronizedThredd - test1 ...i=9,j=1 23:49:32.181 [pool-1-thread-1] INFO com.yanxizhu.demo.concurrency.sync.DemoSynchronizedThredd - test1 ...i=0,j=2 23:49:32.181 [pool-1-thread-1] INFO com.yanxizhu.demo.concurrency.sync.DemoSynchronizedThredd - test1 ...i=1,j=2 23:49:32.181 [pool-1-thread-1] INFO com.yanxizhu.demo.concurrency.sync.DemoSynchronizedThredd - test1 ...i=2,j=2 23:49:32.181 [pool-1-thread-1] INFO com.yanxizhu.demo.concurrency.sync.DemoSynchronizedThredd - test1 ...i=3,j=2 23:49:32.181 [pool-1-thread-1] INFO com.yanxizhu.demo.concurrency.sync.DemoSynchronizedThredd - test1 ...i=4,j=2 23:49:32.181 [pool-1-thread-1] INFO com.yanxizhu.demo.concurrency.sync.DemoSynchronizedThredd - test1 ...i=5,j=2 23:49:32.181 [pool-1-thread-1] INFO com.yanxizhu.demo.concurrency.sync.DemoSynchronizedThredd - test1 ...i=6,j=2 23:49:32.181 [pool-1-thread-1] INFO com.yanxizhu.demo.concurrency.sync.DemoSynchronizedThredd - test1 ...i=7,j=2 23:49:32.181 [pool-1-thread-1] INFO com.yanxizhu.demo.concurrency.sync.DemoSynchronizedThredd - test1 ...i=8,j=2 23:49:32.181 [pool-1-thread-1] INFO com.yanxizhu.demo.concurrency.sync.DemoSynchronizedThredd - test1 ...i=9,j=2*/ //-----------------------------------测试同一对象的方法test2,作用方法------------------------------------------- /* executorService.execute(()->{ demoSynchronizedTwo.test2(1); demoSynchronizedTwo2.test2(2); });*/ /* 输出结果: 23:47:13.674 [pool-1-thread-1] INFO com.yanxizhu.demo.concurrency.sync.DemoSynchronizedThredd - test2 ...i=0,j=1 23:47:13.681 [pool-1-thread-1] INFO com.yanxizhu.demo.concurrency.sync.DemoSynchronizedThredd - test2 ...i=1,j=1 23:47:13.681 [pool-1-thread-1] INFO com.yanxizhu.demo.concurrency.sync.DemoSynchronizedThredd - test2 ...i=2,j=1 23:47:13.681 [pool-1-thread-1] INFO com.yanxizhu.demo.concurrency.sync.DemoSynchronizedThredd - test2 ...i=3,j=1 23:47:13.681 [pool-1-thread-1] INFO com.yanxizhu.demo.concurrency.sync.DemoSynchronizedThredd - test2 ...i=4,j=1 23:47:13.681 [pool-1-thread-1] INFO com.yanxizhu.demo.concurrency.sync.DemoSynchronizedThredd - test2 ...i=5,j=1 23:47:13.681 [pool-1-thread-1] INFO com.yanxizhu.demo.concurrency.sync.DemoSynchronizedThredd - test2 ...i=6,j=1 23:47:13.681 [pool-1-thread-1] INFO com.yanxizhu.demo.concurrency.sync.DemoSynchronizedThredd - test2 ...i=7,j=1 23:47:13.681 [pool-1-thread-1] INFO com.yanxizhu.demo.concurrency.sync.DemoSynchronizedThredd - test2 ...i=8,j=1 23:47:13.681 [pool-1-thread-1] INFO com.yanxizhu.demo.concurrency.sync.DemoSynchronizedThredd - test2 ...i=9,j=1 23:47:13.681 [pool-1-thread-1] INFO com.yanxizhu.demo.concurrency.sync.DemoSynchronizedThredd - test2 ...i=0,j=2 23:47:13.681 [pool-1-thread-1] INFO com.yanxizhu.demo.concurrency.sync.DemoSynchronizedThredd - test2 ...i=1,j=2 23:47:13.681 [pool-1-thread-1] INFO com.yanxizhu.demo.concurrency.sync.DemoSynchronizedThredd - test2 ...i=2,j=2 23:47:13.681 [pool-1-thread-1] INFO com.yanxizhu.demo.concurrency.sync.DemoSynchronizedThredd - test2 ...i=3,j=2 23:47:13.681 [pool-1-thread-1] INFO com.yanxizhu.demo.concurrency.sync.DemoSynchronizedThredd - test2 ...i=4,j=2 23:47:13.681 [pool-1-thread-1] INFO com.yanxizhu.demo.concurrency.sync.DemoSynchronizedThredd - test2 ...i=5,j=2 23:47:13.681 [pool-1-thread-1] INFO com.yanxizhu.demo.concurrency.sync.DemoSynchronizedThredd - test2 ...i=6,j=2 23:47:13.681 [pool-1-thread-1] INFO com.yanxizhu.demo.concurrency.sync.DemoSynchronizedThredd - test2 ...i=7,j=2 23:47:13.681 [pool-1-thread-1] INFO com.yanxizhu.demo.concurrency.sync.DemoSynchronizedThredd - test2 ...i=8,j=2 23:47:13.681 [pool-1-thread-1] INFO com.yanxizhu.demo.concurrency.sync.DemoSynchronizedThredd - test2 ...i=9,j=2*/ executorService.shutdown(); /** * 说明:修饰类和修改静态方法是一样的 */ } }结论:修改类和静态方法,作用效果是一样的。测试:之前计数通过Atomic原子保证互斥性,现在通过Synchronized保证互斥性。package com.yanxizhu.demo.concurrency.sync; import com.yanxizhu.demo.concurrency.annotation.ThreadSafety; import com.yanxizhu.demo.concurrency.annotation.UnThreadSafety; import lombok.extern.slf4j.Slf4j; import java.util.concurrent.CountDownLatch; import java.util.concurrent.ExecutorService; import java.util.concurrent.Executors; import java.util.concurrent.Semaphore; /** * @description: 线程不安全,不正确的 * @author: <a href="mailto:batis@foxmail.com">清风</a> * @date: 2022/4/19 19:28 * @version: 1.0 */ @ThreadSafety @Slf4j public class DemoSemaphoreAndCountDownLatch { //用户数量 private static final int clientsTotal = 5000; //并发数量 private static final int concurrencyTotal = 200; //累加总和 private static int count = 0; public static void main(String[] args) throws InterruptedException { ExecutorService executorService = Executors.newCachedThreadPool(); //信号量 final Semaphore semaphore = new Semaphore(concurrencyTotal); //闭锁 final CountDownLatch countDownLatch = new CountDownLatch(clientsTotal); for (int i = 0; i < clientsTotal; i++) { executorService.execute(()->{ try { semaphore.acquire(); add(); semaphore.release(); } catch (InterruptedException e) { log.error("出现错误:【{}】", e.getMessage()); } countDownLatch.countDown(); }); } countDownLatch.await(); executorService.shutdown(); log.info("累加结果为count=【{}】",count); } /** * 累加 */ private synchronized static void add(){ count++; } }原子性对比synchronized:不可中断锁,适合竞争不激烈,可读性好Lock:可中断锁,多样化同步,竞争激烈时能维持常态Atomic:竞争激烈时能维持常态,比Lock性能好;只能同步一个值
2022年04月21日
169 阅读
0 评论
1 点赞
2022-03-19
线程八锁
线程八锁package com.yanxizhu; /* * 题目:判断打印的 "one" or "two" ? * * 1. 两个普通同步方法,两个线程,标准打印, 打印? //one two * 2. 新增 Thread.sleep() 给 getOne() ,打印? //one two * 3. 新增普通方法 getThree() , 打印? //three one two * 4. 两个普通同步方法,两个 Number 对象,打印? //two one * 5. 修改 getOne() 为静态同步方法,打印? //two one * 6. 修改两个方法均为静态同步方法,一个 Number 对象? //one two * 7. 一个静态同步方法,一个非静态同步方法,两个 Number 对象? //two one * 8. 两个静态同步方法,两个 Number 对象? //one two * * 线程八锁的关键: * ①非静态方法的锁默认为 this, 静态方法的锁为 对应的 Class 实例 * ②某一个时刻内,只能有一个线程持有锁,无论几个方法。 */ public class TestThread8Monitor { public static void main(String[] args) { Number number = new Number(); Number number2 = new Number(); new Thread(new Runnable() { @Override public void run() { number.getOne(); } }).start(); new Thread(new Runnable() { @Override public void run() { //number.getTwo(); number2.getTwo(); } }).start(); /*new Thread(new Runnable() { @Override public void run() { number.getThree(); } }).start();*/ } } class Number{ public static synchronized void getOne(){//Number.class try { Thread.sleep(3000); } catch (InterruptedException e) { } System.out.println("one"); } public synchronized void getTwo(){//this System.out.println("two"); } public void getThree(){ System.out.println("three"); } }一个对象里面如果有多个synchronized方法,某一个时刻内,只要一个线程去调用 其中的一个synchronized方法了,其它的线程都只能等待,换句话说,某一个时刻 内,只能有唯一一个线程去访问这些synchronized方法锁的是当前对象this,被锁定后,其它的线程都不能进入到当前对象的其它的 synchronized方法加个普通方法后发现和同步锁无关换成两个对象后,不是同一把锁了,情况立刻变化。都换成静态同步方法后,情况又变化所有的非静态同步方法用的都是同一把锁——实例对象本身,也就是说如果一个实 例对象的非静态同步方法获取锁后,该实例对象的其他非静态同步方法必须等待获 取锁的方法释放锁后才能获取锁,可是别的实例对象的非静态同步方法因为跟该实 例对象的非静态同步方法用的是不同的锁,所以毋须等待该实例对象已获取锁的非 静态同步方法释放锁就可以获取他们自己的锁。所有的静态同步方法用的也是同一把锁——类对象本身,这两把锁是两个不同的对 象,所以静态同步方法与非静态同步方法之间是不会有竞态条件的。但是一旦一个 静态同步方法获取锁后,其他的静态同步方法都必须等待该方法释放锁后才能获取 锁,而不管是同一个实例对象的静态同步方法之间,还是不同的实例对象的静态同 步方法之间,只要它们同一个类的实例对象!
2022年03月19日
199 阅读
0 评论
6 点赞
2022-03-19
ReentrantLock显示锁
package com.yanxizhu; import java.util.concurrent.locks.Lock; import java.util.concurrent.locks.ReentrantLock; /** * @description: ReentrantLock * @author: <a href="mailto:batis@foxmail.com">清风</a> * @date: 2022/3/19 12:37 * @version: 1.0 */ public class LockDemo { public static void main(String[] args) { titck titck = new titck(); new Thread(titck,"线程1").start(); new Thread(titck,"线程2").start(); new Thread(titck,"线程3").start(); } public static class titck implements Runnable{ Lock lock = new ReentrantLock(); private int titck = 100; @Override public void run() { while(true){ lock.lock(); try{ if(titck>0){ try { Thread.sleep(200); } catch (InterruptedException e) { e.printStackTrace(); } System.out.println("剩余票数:"+--titck); } }finally { lock.unlock(); } } } } } synchronized:隐式锁1、同步代码块2、同步方法jdk1.5之后:显示锁3、同步锁Lock注意:是一个显示锁,需要通过lock()方法上锁,必须通过unlock()方法进行释放锁。
2022年03月19日
136 阅读
0 评论
3 点赞
2022-03-08
高并发中集合问题
第一代线程安全集合类Vector、Hashtable是怎么保证线程安排的:使用synchronized修饰方法缺点:效率低下第二代线程非安全集合类ArrayList、HashMap线程不安全,但是性能好,用来替代Vector、Hashtable使用ArrayList、HashMap,需要线程安全怎么办呢?使用Collections.synchronizedList(list);Collections.synchronizedMap(m);底层使用synchronized代码块锁虽然也是锁住了所有的代码,但是锁在方法里边,并所在方法外边性能可以理解为稍有提高吧。毕竟进方法本身就要分配资源的第三代线程安全集合类在大量并发情况下如何提高集合的效率和安全呢?java.util.concurrent.*ConcurrentHashMap:CopyOnWriteArrayList:CopyOnWriteArraySet:注意不是CopyOnWriteHashSet*底层大都采用Lock锁(1.8的ConcurrentHashMap不使用Lock锁),保证安全的同时,性能也很高。
2022年03月08日
149 阅读
0 评论
2 点赞