方法同步的弊端

方法同步的时候,如果一个方法需要线程安全控制的代码速度其实很快,但是有其他的业务逻辑代码耗时非常长(比如网络请求),这样所有的线程就在这一块就等待着了,这样造成了极大的资源浪费如果并发量很大,可能会造成系统崩溃。(并发的线程遇到synchronized同步的方法,变成串行....)

并发访问-代码块同步

语法:

synchronized (要锁住的对象) {
  并发执行且不耗时的业务计算代码;
}
 
代码示例: 方法同步比代码块同步耗时天壤地别
import java.util.HashSet;
import java.util.Set; /**
* @ClassName ThreadSyncCode
* @projectName: object1
* @author: Zhangmingda
* @description: XXX
* date: 2021/4/22.
*/
public class ThreadSyncCode {
//子线程类外公共用来计算的变量
private static int num = 0;
//子线程对象
private static class MyRannable implements Runnable {
@Override
public void run() { //这里synchronized 导致耗时的IO操作也变为串行
/**
* 模拟网络IO,磁盘IO耗时等待操作
*/
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
/**
* 避免多线程同时计算的代码块改为同步代码块。变为多线程到此串行执行;上面的IO耗时操作仍然并行
*/
synchronized (getClass()){
for (int i=0; i<1000; i++){
num++;
}
}
System.out.println(Thread.currentThread().getName() + " num result:" + num);
}
}
public static void main(String[] args) {
Set<Thread> threads = new HashSet<>();
MyRannable myRannable = new MyRannable();
for (int i=0; i<5; i++){
threads.add(new Thread(myRannable,"线程"+i));
}
threads.forEach(thread -> thread.start()); try {
Thread.sleep(6000);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println("main num result:" + num);
} }

方法同步IO耗时串行导致长达5S出结果。而代码块同步耗时1S多结束。

String作为被锁的对象

import java.util.HashSet;
import java.util.Set; /**
* @ClassName ThreadMultiObjectSyncStringLock
* @projectName: object1
* @author: Zhangmingda
* @description: XXX
* date: 2021/4/22.
*/
public class ThreadMultiObjectSyncStringLock {
private static int num = 0;
private static class MyThread extends Thread{
private String lock; public MyThread(String name, String lock) {
super(name);
this.lock = lock;
} @Override
public void run() {
synchronized (lock){
for (int i=0; i<1000; i++){
num++;
}
System.out.println(Thread.currentThread().getName() + " num:" + num);
}
}
}
public static void main(String[] args) {
//String锁对象
String lock = "LOCK";
//存放线程的集合
Set<MyThread> myThreads = new HashSet<>();
//向集合添加线程实例
for (int i=0; i<5; i++){
myThreads.add(new MyThread("T" +i, lock));
}
//启动所有线程
myThreads.forEach(myThread -> myThread.start());
//稍等时间主线程查看结果
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println(Thread.currentThread().getName() + "num Result:" + num); //5000完全正确
}
}
结果:最终打印出来的num的值就是5000,结果是正确的。但是我们发现我们在for循环创建我们的线程的时候,我们定义了5次lock,但是实际上这些lock是同一个对象(指向的是同一个内存地址),因为在JAVA中,字符串具有常量缓存的功能。所以会被锁起来。

java 多线程: Thread 并发访问-代码块同步synchronized {};String作为被锁的对象的更多相关文章

  1. “全栈2019”Java多线程第十六章:同步synchronized关键字详解

    难度 初级 学习时间 10分钟 适合人群 零基础 开发语言 Java 开发环境 JDK v11 IntelliJ IDEA v2018.3 文章原文链接 "全栈2019"Java多 ...

  2. java 多线程:Thread 并发线程: 方法同步synchronized关键字,与static的结合

    1.方法内的变量是安全的 方法内定义的变量,每个变量对应单独的内存变量地址,多个线程之间相互不影响.多个线程之间的变量根本没有一毛钱关系 public class ThreadFuncVarSafe ...

  3. Java多线程和并发(八),synchronized底层原理

    目录 1.对象头(Mark Word) 2.对象自带的锁(Monitor) 3.自旋锁和自适应自旋锁 4.偏向锁 5.轻量级锁 6.偏向锁,轻量级锁,重量级锁联系 八.synchronized底层原理 ...

  4. Java多线程和并发(七),synchronized

    目录 1.线程安全的主要原因 2.互斥锁的特性 3.锁的类别 4.类锁和对象锁的总结 七.synchronized 1.线程安全的主要原因 2.互斥锁的特性 Java中synchronized锁的不是 ...

  5. Java多线程与并发库高级应用-同步集合

    ArrayBlockingQueue LinkedBlockingQueue 数组是连续的一片内存 链表是不连续的一片内存  传统方式下用Collections工具类提供的synchronizedCo ...

  6. 对象及变量的并发访问(同步方法、同步代码块、对class进行加锁、线程死锁)&内部类的基本用法

    主要学习多线程的并发访问,也就是使得线程安全. 同步的单词为synchronized,异步的单词为asynchronized 同步主要就是通过锁的方式实现,一种就是隐式锁,另一种是显示锁Lock,本节 ...

  7. java多线程中并发集合和同步集合有哪些?区别是什么?

    java多线程中并发集合和同步集合有哪些? hashmap 是非同步的,故在多线程中是线程不安全的,不过也可以使用 同步类来进行包装: 包装类Collections.synchronizedMap() ...

  8. Java 多线程高并发编程 笔记(一)

    本篇文章主要是总结Java多线程/高并发编程的知识点,由浅入深,仅作自己的学习笔记,部分侵删. 一 . 基础知识点 1. 进程于线程的概念 2.线程创建的两种方式 注:public void run( ...

  9. Java 多线程基础(五)线程同步

    Java 多线程基础(五)线程同步 当我们使用多个线程访问同一资源的时候,且多个线程中对资源有写的操作,就容易出现线程安全问题. 要解决上述多线程并发访问一个资源的安全性问题,Java中提供了同步机制 ...

随机推荐

  1. [IIS]文件夹权限

    发布完iis,默认的 Application Pool 没有权限访问文件夹. 可以给项目文件夹添加用户权限. 右键 - "属性" - "安全" - " ...

  2. Topcoder 12519 ScotlandYard(点对 dp+最长路)

    题面传送门 题意: 有两个人 A 和 B 玩一个游戏.游戏规则大致是这样的: 有 \(n\) 个城市和三种交通工具公交.地铁和出租车. 给出三个 \(n\times n\) 的字符矩阵 \(b,m,t ...

  3. 流量限制器(Flux Limiter)

    内容翻译自Wikipedia Flux limiter 流量限制器(Flux limiters)应用在高精度格式中-这种数值方法用来求解科学与工程问题,特别是由偏微分方程(PDE's)描述的流体动力学 ...

  4. [R] 添加误差棒的分组折线图:geom_path: Each group consists of only one observation. Do you need to adjust the...

    想做一个简单的分组折线图,并添加误差棒,类似下面这样的: 用ggplot似乎很简单就能实现:ggplot+geom_errorbar+geom_line+geom_point,重点在于计算误差棒. 还 ...

  5. tabix 操作VCF文件

    tabix 可以对NGS分析中常见格式的文件建立索引,从而加快访问速度,不仅支持VCF文件,还支持BED, GFF,SAM等格式. 下载地址: 1 https://sourceforge.net/pr ...

  6. PHP识别二维码(php-zbarcode)

    PHP识别二维码(php-zbarcode) 标签: php二维码扩展 2015-11-06 17:12 609人阅读 评论(0) 收藏 举报  分类: PHP(1)  Linux 版权声明:本文为博 ...

  7. Scrapy-Splash的安装和使用

    Scrapy-Splash是一个Scrapy中支持JavaScript渲染的工具. Scrapy-Splash的安装分为两部分.一个是Splash服务的安装,具体是通过Docker,安装之后,会启动一 ...

  8. Oracle中如何自定义类型

    一:Oracle中的类型有很多种,主要可以分为以下几类:1.字符串类型.如:char.nchar.varchar2.nvarchar2.2.数值类型.如:int.number(p,s).integer ...

  9. LeetCode33题——搜索旋转排序数组

    1.题目描述 假设按照升序排序的数组在预先未知的某个点上进行了旋转. ( 例如,数组 [0,1,2,4,5,6,7] 可能变为 [4,5,6,7,0,1,2] ). 搜索一个给定的目标值,如果数组中存 ...

  10. linux添加用户、权限

    # useradd –d /usr/sam -m sam 此命令创建了一个用户sam,其中-d和-m选项用来为登录名sam产生一个主目录/usr/sam(/usr为默认的用户主目录所在的父目录). 假 ...