博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
对synchronized的使用一点浅解
阅读量:4181 次
发布时间:2019-05-26

本文共 9304 字,大约阅读时间需要 31 分钟。

synchronized是Java中的关键字,是一种同步锁。它修饰的对象有以下几种:

  1. 修饰一个代码块,被修饰的代码块称为同步语句块,其作用的范围是大括号{}括起来的代码,作用的对象是调用这个代码块的对象;
  2. 修饰一个方法,被修饰的方法称为同步方法,其作用的范围是整个方法,作用的对象是调用这个方法的对象;
  3. 修改一个静态的方法,其作用的范围是整个静态方法,作用的对象是这个类的所有对象;
  4. 修改一个类,其作用的范围是synchronized后面括号括起来的部分,作用主的对象是这个类的所有对象。

一、修饰代码块

package com.xiaobu.synchronizedTest;/** * @author xiaobu * @version JDK1.8.0_171 * @date on  2020/6/24 10:53 * @description  一个线程访问一个对象中的synchronized(this)同步代码块时,其他试图访问该对象的线程将被阻塞。 */public class SyncThreadDemo1 implements Runnable {
private static int count; public SyncThreadDemo1() {
count = 0; } public void run() {
synchronized(this) {
for (int i = 0; i < 5; i++) {
try {
System.out.println(Thread.currentThread().getName() + ":" + (count++)); Thread.sleep(100); } catch (InterruptedException e) {
e.printStackTrace(); } } } } /** * SyncThread1:0 * SyncThread1:1 * SyncThread1:2 * SyncThread1:3 * SyncThread1:4 * SyncThread2:5 * SyncThread2:6 * SyncThread2:7 * SyncThread2:8 * SyncThread2:9 */ public static void main(String[] args) {
SyncThreadDemo1 syncThread = new SyncThreadDemo1(); Thread thread1 = new Thread(syncThread,"SyncThread1"); Thread thread2 = new Thread(syncThread, "SyncThread2"); thread1.start(); thread2.start(); }}
package com.xiaobu.synchronizedTest;/** * @author xiaobu * @version JDK1.8.0_171 * @date on  2020/6/24 10:53 * @description 锁不同的对象 */public class SyncThreadDemo2 implements Runnable {
private static int count; public SyncThreadDemo2() {
count = 0; } public void run() {
synchronized(this) {
for (int i = 0; i < 5; i++) {
try {
System.out.println(Thread.currentThread().getName() + ":" + (count++)); Thread.sleep(100); } catch (InterruptedException e) {
e.printStackTrace(); } } } } /** * SyncThread2:0 * SyncThread1:1 * SyncThread2:2 * SyncThread1:2 * SyncThread2:3 * SyncThread1:4 * SyncThread2:5 * SyncThread1:5 * SyncThread1:6 * SyncThread2:6 * synchronized锁定的是对象,这时会有两把锁分别锁定syncThread1对象和syncThread2对象, * 而这两把锁是互不干扰的,不形成互斥,所以两个线程可以同时执行 */ public static void main(String[] args) {
Thread thread1 = new Thread(new SyncThreadDemo2(),"SyncThread1"); Thread thread2 = new Thread(new SyncThreadDemo2(), "SyncThread2"); thread1.start(); thread2.start(); }}
package com.xiaobu.synchronizedTest;import java.util.concurrent.atomic.AtomicInteger;/** * @author xiaobu * @version JDK1.8.0_171 * @date on  2020/6/24 10:53 * @description */public class SyncThreadAtomicIntegerDemo implements Runnable {
private static AtomicInteger count; public SyncThreadAtomicIntegerDemo() {
count = new AtomicInteger(0); } @Override public void run() {
synchronized(this) {
for (int i = 0; i < 5; i++) {
try {
System.out.println(Thread.currentThread().getName() + ":" + (count.incrementAndGet())); Thread.sleep(100); } catch (InterruptedException e) {
e.printStackTrace(); } } } } /** * SyncThread1:1 * SyncThread2:2 * SyncThread1:3 * SyncThread2:4 * SyncThread1:5 * SyncThread2:6 * SyncThread1:7 * SyncThread2:8 * SyncThread1:9 * SyncThread2:10 * * 原本是线程不安全的 AtomicInteger是原子类 导致数据的安全性 */ public static void main(String[] args) {
SyncThreadAtomicIntegerDemo syncThread = new SyncThreadAtomicIntegerDemo(); Thread thread1 = new Thread(new SyncThreadAtomicIntegerDemo(),"SyncThread1"); Thread thread2 = new Thread(new SyncThreadAtomicIntegerDemo(), "SyncThread2"); thread1.start(); thread2.start(); }}

二、多个线程访问synchronized和非synchronized代码块

package com.xiaobu.synchronizedTest;/** * @author xiaobu * @version JDK1.8.0_171 * @date on  2020/6/24 10:53 * @description * countAdd是一个synchronized的,printCount是非synchronized的。 * 从上面的结果中可以看出一个线程访问一个对象的synchronized代码块时, * 别的线程可以访问该对象的非synchronized代码块而不受阻塞。 */public class SyncThreadCounter implements Runnable {
private int count; public SyncThreadCounter() {
count = 0; } public void countAdd() {
synchronized(this) {
for (int i = 0; i < 5; i ++) {
try {
System.out.println(Thread.currentThread().getName() + ":" + (count++)); Thread.sleep(100); } catch (InterruptedException e) {
e.printStackTrace(); } } } } //非synchronized代码块,未对count进行读写操作,所以可以不用synchronized public void printCount() {
for (int i = 0; i < 5; i ++) {
try {
System.out.println(Thread.currentThread().getName() + " count:" + count); Thread.sleep(100); } catch (InterruptedException e) {
e.printStackTrace(); } } } public void run() {
String threadName = Thread.currentThread().getName(); if (threadName.equals("A")) {
countAdd(); } else if (threadName.equals("B")) {
printCount(); } } /** * B count:0 * A:0 * B count:1 * A:1 * B count:2 * A:2 * A:3 * B count:4 * A:4 * B count:5 */ public static void main(String[] args) {
SyncThreadCounter counter = new SyncThreadCounter(); Thread thread1 = new Thread(counter, "A"); Thread thread2 = new Thread(counter, "B"); thread1.start(); thread2.start(); }}

三、指定要给某个对象加锁

当有一个明确的对象作为锁时,就可以用类似下面这样的方式写程序。

public void method3(SomeObject obj){
//obj 锁定的对象 synchronized(obj) {
// todo }}

当没有明确的对象作为锁,只是想让一段代码同步时,可以创建一个特殊的对象来充当锁:

class Test implements Runnable{
private byte[] lock = new byte[0]; // 特殊的instance变量 public void method() {
synchronized(lock) {
// todo 同步代码块 } } public void run() {
}}

说明:零长度的byte数组对象创建起来将比任何对象都经济――查看编译后的字节码:生成零长度的byte[]对象只需3条操作码,而Object lock = new Object()则需要7行操作码。

四、修饰一个方法

public synchronized void method(){
// todo}

<==>等价于

public  void method(){
synchronized(this){
// todo }}

修饰静态方法

package com.xiaobu.synchronizedTest;/** * @author xiaobu * @version JDK1.8.0_171 * @date on  2020/6/24 10:53 * @description  synchronized 修饰静态方法相当于锁的对象是类的实例,即锁定的是这个类的所有对象 */public class SyncThreadStaticDemo1 implements Runnable {
private static int count; public SyncThreadStaticDemo1() {
count = 0; } public static synchronized void method() {
for (int i = 0; i < 5; i++) {
try {
System.out.println(Thread.currentThread().getName() + ":" + (count++)); Thread.sleep(100); } catch (InterruptedException e) {
e.printStackTrace(); } } } @Override public void run() {
method(); } /** * SyncThread1:0 * SyncThread1:1 * SyncThread1:2 * SyncThread1:3 * SyncThread1:4 * SyncThread2:5 * SyncThread2:6 * SyncThread2:7 * SyncThread2:8 * SyncThread2:9 */ public static void main(String[] args) {
SyncThreadStaticDemo1 syncThread = new SyncThreadStaticDemo1(); Thread thread1 = new Thread(syncThread,"SyncThread1"); Thread thread2 = new Thread(syncThread, "SyncThread2"); thread1.start(); thread2.start(); }}

五、修饰一个类

package com.xiaobu.synchronizedTest;/** * @author xiaobu * @version JDK1.8.0_171 * @date on  2020/6/24 10:53 * @description  synchronized 修饰类,即锁定的是这个类的所有对象 */public class SyncThreadStaticDemo2 implements Runnable {
private static int count; public SyncThreadStaticDemo2() {
count = 0; } public static void method() {
synchronized (SyncThreadStaticDemo2.class){
for (int i = 0; i < 5; i++) {
try {
System.out.println(Thread.currentThread().getName() + ":" + (count++)); Thread.sleep(100); } catch (InterruptedException e) {
e.printStackTrace(); } } } } @Override public void run() {
method(); } /** * SyncThread1:0 * SyncThread1:1 * SyncThread1:2 * SyncThread1:3 * SyncThread1:4 * SyncThread2:5 * SyncThread2:6 * SyncThread2:7 * SyncThread2:8 * SyncThread2:9 */ public static void main(String[] args) {
SyncThreadStaticDemo2 syncThread = new SyncThreadStaticDemo2(); Thread thread1 = new Thread(syncThread,"SyncThread1"); Thread thread2 = new Thread(syncThread, "SyncThread2"); thread1.start(); thread2.start(); }}

SyncThreadStaticDemo1和SyncThreadStaticDemo2是等价的

参考:

转载地址:http://yzgai.baihongyu.com/

你可能感兴趣的文章
Redis常见面试题
查看>>
JDK重要包和Java学习方法论
查看>>
网络通讯中的三次握手与四次挥手原理详解
查看>>
小米为什么做不出高端手机?
查看>>
送30本技术书籍
查看>>
面试明明聊的很开心,为什么要挂我!
查看>>
熬夜加班身体被掏空,程序员的压力究竟有多大
查看>>
程序员轻松绘图神器
查看>>
工作中99%能用到的git命令
查看>>
给程序员入门的10点建议!
查看>>
送 35 本 Python 入门书籍
查看>>
如何快速上手Linux操作系统?
查看>>
微信QQ等主流应用上线国产系统UOS:界面曝光
查看>>
3天,让你的C++从入门到精通
查看>>
这个「微信年度报告」你被骗了吗?
查看>>
可怕啊,阿里面试!
查看>>
疯传!某大厂P8面试题库遭到泄露!
查看>>
中国编程第一人,一人抵一城!
查看>>
【微信红包封面】最新!最全!
查看>>
最近线上发生的两个坑爹锅!
查看>>