[总结] Synchronized汇总
Java中的每一个对象都可以作为锁。
- 1对于同步方法,锁是当前实例对象。
- 2对于静态同步方法,锁是当前对象的Class对象。
- 3对于同步方法块,锁是Synchonized括号里配置的对象。
当一个线程试图访问同步代码块时,它首先必须得到锁,退出或抛出异常时必须释放锁。
我们常引入对象锁和类锁的概念来有助于了解上面的3点论述。
(1)对象锁(对象实例锁)即Synchronized用于对象实例方法,或者一个对象实例上的锁。
(2)类锁是用于类的静态方法或者一个类的class对象上的。
对象锁锁定的是当前实例对象。一个类可以有无数个对象实例,所以一个类可以有无数个对象实例锁。但是每个类只有一个class对象,同一个对象的所有不同对象实例的对象锁是互不干扰的,但是每个类只有一个类锁(意味着争夺类锁或者同一个实例的对象锁就会出现同步/锁竞争的情况)。(同时注意: olddoor: 类锁和对象锁并不排斥.)
其实类锁只是一个概念上的东西,并不是真实存在的,它只是用来帮助我们理解锁定实例方法和静态方法的区别的。
* synchronized(this.getClass())/synchronized(类.class)或者synchronized(类的静态变量)或者修饰静态方法.则是锁定类.
比如classs Entity的方法:
public synchronized void objLock(String who){ //使用synchronized修饰方法
for (int i = 0; i < 100; i++) {
System.out.println(who + "-" + i);
}
}
线程类TestThread13如下:
package com.j2se.ThreadTest.test001;
import java.util.Date;
public class TestThread13 extends Thread {
private Entity e;
public TestThread13(Entity e,String name) {
super(name);
this.e=e;
}
public TestThread13(String name) {
super(name);
this.e=e;
}
public void run() {
Entity e =new Entity();
e.objLock(super.getName());//打印当前线程名字
}
}
写一个执行类的main方法执行内容如下
TestThread13 t133=new TestThread13("133");// 实例锁
TestThread13 t1333=new TestThread13("1333"); // 实例锁
t133.start();
t1333.start();
执行效果
1333-0
1333-1
1333-2
133-0
133-1
133-2
133-3
133-4
发现交替打印. 因为线程t133和t1333执行run方法调用Entity.objLock时候调用竞争的是不同的对象实例。
即不同的对象实例锁之间互不干扰(多线程使用不同的对象实例锁),不存在同步竞争情况。
将调用方法改一下
将TestThread13的run方法中的Entity初始化注释
public void run() {
// Entity e =new Entity(); //注释初始化
e.objLock(super.getName());//打印当前线程名字
}
Entity e =new Entity(); //初始化唯一的一个实例,用于传入线程
TestThread13 t133=new TestThread13(e,"133");//
TestThread13 t1333=new TestThread13(e,"1333"); //
t133.start();
t1333.start();
133-0
133-1
133-2
133-3
133-4
133-5
133-6
133-7
133-8
public class TestThread14 extends Thread {
private Entity e;
public TestThread14(Entity e,String name) {
super(name);
this.e=e;
}
public TestThread14(String name) {
super(name);
this.e=e;
}
public void run() {
Entity e =new Entity();
e.classLock(super.getName());//打印当前线程名字
}
}
public synchronized static void classLock(String who){
for (int i = 0; i < 100; i++) {
System.out.println(who + "-" + i);
}
}
TestThread14 t14=new TestThread14("14");//
TestThread14 t144=new TestThread14("144"); //
t14.start();
t144.start();
14-0
14-1
14-2
14-3
14-4
14-5
14-6
...
public void run() {
// Entity e =new Entity();
e.classLock(super.getName());//打印当前线程名字
}
Entity e=new Entity();
TestThread13 t13=new TestThread13(e,"13");//
TestThread14 t14=new TestThread14(e,"14");//
t14.start();
t13.start();
14-0
13-0
13-1
14-1
13-2
public void snycThis(String who) {
synchronized (this) {
for (int i = 0; i < 100; i++) {
System.out.println(who + "-" + i);
}
}
}
package com.j2se.ThreadTest.test001;
import java.util.Date;
public class TestThread15 extends Thread {
private Entity e;
public TestThread15(Entity e,String name) {
super(name);
this.e=e;
}
public TestThread15(String name) {
super(name);
this.e=e;
}
public void run() {
Entity e =new Entity();
e.snycThis(super.getName());
}
}
TestThread15 t15=new TestThread15("15");//
TestThread15 t155=new TestThread15("155");//
t15.start();
t155.start();
155-0
15-0
155-1
15-1
155-2
Entity e=new Entity();
TestThread15 t15=new TestThread15(e,"15");//
TestThread15 t155=new TestThread15(e,"155");//
t15.start();
t155.start();
public void run() {
// Entity e =new Entity(); //不自己初始化, 使用外部传入的对象实例
e.snycThis(super.getName());
}
15-0
15-1
15-2
15-3
15-4
15-5
15-6
15-7
15-8
15-9
15-10
15-11
Entity e=new Entity();
TestThread15 t15=new TestThread15(e,"15");//
TestThread13 t13=new TestThread13(e,"13");//
t15.start();
t13.start();
15-0
15-1
15-2
15-3
15-4
15-5
15-6
15-7
15-8
public synchronized void objLock(String who){
for (int i = 0; i < 100; i++) {
System.out.println(who + "-" + i);
}
}
public void snycThis(String who) {
synchronized (this) {
for (int i = 0; i < 100; i++) {
System.out.println(who + "-" + i);
}
}
}
public void snycClass(String who) {
synchronized (Entity.class) {
for (int i = 0; i < 100; i++) {
System.out.println(who + "-" + i);
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
}
public synchronized static void classLock(String who){
for (int i = 0; i < 100; i++) {
System.out.println(who + "-" + i);
}
}
public class Entity {
public String name = "entity";
private static byte[] lock = new byte[0];
private Integer integer=0;
private static LinkedList<AlarmVo> volist = new LinkedList<AlarmVo>();
private String strLock="1";
public void snycstrLock(String who) {
synchronized (strLock) {
for (int i = 0; i < 100; i++) {
System.out.println(who + "-" + i);
}
}
}
- public class ThreadTest_02 extends Thread{
- private String lock ;
- private String name;
- public ThreadTest_02(String name,String lock){
- this.name = name;
- this.lock = lock;
- }
- @Override
- public void run() {
- synchronized (lock) {
- for(int i = 0 ; i < 3 ; i++){
- System.out.println(name + " run......");
- }
- }
- }
- public static void main(String[] args) {
- String lock = new String("test");
- for(int i = 0 ; i < 5 ; i++){
- new ThreadTest_02("ThreadTest_" + i,lock).start(); //已改为1个线程的run方法请求5次
- }
- }
- }
运行结果:
ThreadTest_0 run......
ThreadTest_0 run......
ThreadTest_0 run......
ThreadTest_1 run......
ThreadTest_1 run......
ThreadTest_1 run......
ThreadTest_4 run......
ThreadTest_4 run......
ThreadTest_4 run......
ThreadTest_3 run......
ThreadTest_3 run......
ThreadTest_3 run......
ThreadTest_2 run......
ThreadTest_2 run......
ThreadTest_2 run......
在main方法中我们创建了一个String对象lock,并将这个对象赋予每一个ThreadTest2线程对象的私有变量lock。我们知道java中存在一个字符串池,那么这些线程的lock私有变量实际上指向的是堆内存中的同一个区域(加锁则需获取堆内存区域的锁),即存放main函数中的lock变量的区域,所以对象锁是唯一且共享的。线程同步!!
在这里synchronized锁住的就是lock这个String对象。{利用String变量指向的是堆内存这一情况, 每个线程实例调用方法时都获取类变量String lock的锁,以此达到同步的效果}
综上 是否可以深刻理解了本文第一句 "Java中的每一个对象都可以作为锁。"
[总结] Synchronized汇总的更多相关文章
- Synchronized的实现原理(汇总)
一.Java中synchronized关键字的作用 总所周知,在并发环境中多个线程对同一个资源进行访问很可能出现脏读等一系列线程安全问题.这时我们可以用加锁的方式对访问共享资源的代码块进行加锁,以 ...
- [CareerCup] 16.6 Synchronized Method 同步方法
16.6 You are given a class with synchronized method A and a normal method B. If you have two threads ...
- 史上最全的 Java 新手问题汇总
史上最全的 Java 新手问题汇总 Java是目前最流行的编程语言之一——它可以用来编写Windows程序或者是Web应用,移动应用,网络程序,消费电子产品,机顶盒设备,它无处不在. 有超过30亿 ...
- 【转】Java方向如何准备BAT技术面试答案(汇总版)
原文地址:http://www.jianshu.com/p/1f1d3193d9e3 这个主题的内容之前分三个篇幅分享过,导致网络上传播的比较分散,所以本篇做了一个汇总,同时对部分内容及答案做了修改, ...
- java面试笔试大汇总
java面试笔试题大汇总5 JAVA相关基础知识 1.面向对象的特征有哪些方面 1.抽象:2.继承:3.封装:4. 多态性: 2.String是最基本的数据类型吗? 基本数据类型包括byte.int. ...
- (转)Synchronized(对象锁)和Static Synchronized(类锁)的区别
场景:面试的时候经常用得到! 1 综述 Synchronized和Static Synchronized区别 一个是实例锁(锁在某一个实例对象上,如果该类是单例,那么该锁也具有全局锁的概念),一个是全 ...
- Java面试系列之HashMap大扫盲汇总
PS:整理的稍微有点急,不足之处,望各路道友指正,List相关可以查看前一篇随笔! HashMap的工作原理是近年来常见的Java面试题,几乎每个Java程序员都知道HashMap,都知道哪里要用Ha ...
- 线程池 队列 synchronized
线程池 BlockingQueue synchronized volatile 本章从线程池到阻塞队列BlockingQueue.从BlockingQueue到synchronized 和 volat ...
- 并发的核心:CAS 与synchronized, Java8是如何优化 CAS 的?
大家可能都听说说 Java 中的并发包,如果想要读懂 Java 中的并发包,其核心就是要先读懂 CAS 机制,因为 CAS 可以说是并发包的底层实现原理. 今天就带大家读懂 CAS 是如何保证操作的原 ...
随机推荐
- 开始 第一个自己的python爬虫程序 爬磁力链
不能一事无成,这么久了学python还是吊着,要落地,落在博客园好了,好像公司也只能上博客园了 昨天看了一篇用正则爬电影天堂的视频,直接拿来用,爬磁力吧,爬好玩的 #导入模块 import reque ...
- Oracle误删除数据和表的恢复办法包括truncate
在工作中我们操作数据库的时候经常会发生一个不该发生的问题:用户意外的删除一个非常重要的表或者是表中的数据而且没有备份,需要尽快的恢复,以下就是解决的办法: 主要是利用Oracle回收站的闪回特性ora ...
- Linux系统上安装、卸载JAVA、TOMCAT的方法
一. 安装JAVA 安装方法1:手工上传 创建安装目录上传JAVA安装包 Normal 0 7.8 磅 0 2 false false false EN-US ZH-CN X-NONE /* Styl ...
- vue+element-ui实现表格编辑(增加或删除行,删除单行或删除多行)
<template> <div class="app-container"> <div class="filter-container&qu ...
- 利用python执行shell脚本 并动态传参 及subprocess基本使用
最近工作需求中 有遇到这个情况 在web端获取配置文件内容 及 往shell 脚本中动态传入参数 执行shell脚本这个有多种方法 最后还是选择了subprocess这个python标准库 su ...
- 如何通过Chrome远程调试android设备上的Web网站
网上的帖子很多,但很多都是老版本的,试过了,根本不管用,花了一天时间,终于在本机试验通过了,特记录下来,以备用.有需要的朋友也可以参考.先上一张图,看看PC端chrome上调试的效果: 左边是手机的模 ...
- Ubuntu 安装 uget
PPA方式 sudo add-apt-repository ppa:plushuang-tw/uget-stable sudo apt update sudo apt install uget -y ...
- 常见Soc平台图形内存管理学习笔记
硬件编解码.硬件图像scale等过程,是在专有的硬件单元里进行,其使用的内存也是专有的内存,这种内存多是SoC中图形内存.如此方便与硬件加速图形渲染.图像显示.硬件图像加速处理等功能相交互. 上述过程 ...
- sublime新建工程文件夹
点击project,选择add folder to project,显示如图 点击选择以后跳转至你存放sublime的文件的workspace中,需要提前在workspace中新建文件夹,点击add ...
- java中next()和nextLine()的区别
首先,next()一定要读取到有效字符后才可以结束输入,对输入有效字符之前遇到的空格键.Tab键或Enter键等结束符,next()方法会自动将其去掉,只有在输入有效字符之后,next()方法才将其后 ...