Java并发编程_synchronized关键字的用法(一)
synchronized:意思是 同步,也就是 共享资源
Synchronized修饰方法:对象锁
Static Synchronized修饰方法:类锁
下面代码手动敲一遍,就会理解
一、Synchronized修饰方法
1、一个对象,启动多个线程,竞争一把对象锁
package sync;
/*
* 一个对象,启动多个线程,竞争一把对象锁
*/
public class MyThread extends Thread{ private int count = 5; public synchronized void run() {
count--;
System.out.println(this.currentThread().getName() + " count = " + count);
} public static void main(String[] args) {
//新建一个对象
MyThread myThread = new MyThread();
//启动多个线程
Thread t1 = new Thread(myThread,"t1");
Thread t2 = new Thread(myThread,"t2");
Thread t3 = new Thread(myThread,"t3");
Thread t4 = new Thread(myThread,"t4");
Thread t5 = new Thread(myThread,"t5");
t1.start();
t2.start();
t3.start();
t4.start();
t5.start();
}
}
输出结果:
t1 count = 4
t4 count = 3
t5 count = 2
t3 count = 1
t2 count = 0
这五个线程,哪个先执行,哪个后执行,要看CPU调度
2、多个对象,启动多个线程,竞争多把对象锁
package sync;
public class MultiThread {
private int num = 0;
public synchronized void printNum(String tag) {
try {
if(tag.equals("a")) {
num = 100;
System.out.println("tag a , set num over!");
Thread.sleep(1000);
System.out.println("tag " + tag + ", num = " + num);
}else {
num = 200;
System.out.println("tag b , set num over!");
Thread.sleep(1000);
System.out.println("tag " + tag + ", num = " + num);
}
} catch (InterruptedException e) {
e.printStackTrace();
}
}
public static void main(String[] args) {
//新建两个对象m1 、m2
MultiThread m1 = new MultiThread();
MultiThread m2 = new MultiThread();
//新建第一个线程,调用m1对象的printNum()方法
Thread t1 = new Thread(new Runnable() {
@Override
public void run() {
m1.printNum("a");
}
});
//新建第二个线程,调用m2对象的printNum()方法
Thread t2 = new Thread(new Runnable() {
@Override
public void run() {
m2.printNum("b");
}
});
//同时启动两个线程
t1.start();
t2.start();
//是先执行完线程t1,再执行线程t2吗?
}
}
输出结果:
tag b , set num over!
tag a , set num over!
tag b, num = 200
tag a, num = 100
可以看到,线程t1和线程t2是同时执行,两个线程互不影响,独立执行,因此输出结果自然不分先后.
第一个对象m1访问后,锁住m1这个对象;然后,第二个对象m2继续访问,不会被m1锁影响到。
结论:
(1)synchronized是对象锁,多个对象多个锁,锁的是对象。
(2)而不是把一个方法或者一个类当作锁(一个Class类可以new多个对象嘛)
二、Static Synchronized修饰方法
在静态方法上加上synchronized关键字,表示锁定class类,类一级别的锁(独占class类)
无论new多少个对象去访问该静态synchronized方法,都要排队一个个访问,竞争同一把锁(class这个锁)
package sync;
public class MultiThread {
private static int num = 0;
public static synchronized void printNum(String tag) {
try {
if(tag.equals("a")) {
num = 100;
System.out.println("tag a , set num over!");
Thread.sleep(1000);
System.out.println("tag " + tag + ", num = " + num);
}else {
num = 200;
System.out.println("tag b , set num over!");
Thread.sleep(1000);
System.out.println("tag " + tag + ", num = " + num);
}
} catch (InterruptedException e) {
e.printStackTrace();
}
}
public static void main(String[] args) {
//新建两个对象m1 、m2
MultiThread m1 = new MultiThread();
MultiThread m2 = new MultiThread();
//新建第一个线程,调用m1对象的printNum()方法
Thread t1 = new Thread(new Runnable() {
@Override
public void run() {
m1.printNum("a");
}
});
//新建第二个线程,调用m2对象的printNum()方法
Thread t2 = new Thread(new Runnable() {
@Override
public void run() {
m2.printNum("b");
}
});
//同时启动两个线程
t1.start();
t2.start();
//是先执行完线程t1,再执行线程t2吗?
}
}
输出结果:
tag b , set num over!
tag b, num = 200
tag a , set num over!
tag a, num = 100
可以看到:
先执行完一个线程b,再执行下一个线程a
结论:
(1)static synchronized是类锁,锁住这个类
Java并发编程_synchronized关键字的用法(一)的更多相关文章
- Java并发编程_volatile关键字的用法(二)
被volatile修饰的变量能够保证每个线程能够获取该变量的最新值,从而避免出现数据脏读的现象. 根据下面实例理解: package sync; public class VolatileTest e ...
- Java并发编程 Volatile关键字解析
volatile关键字的两层语义 一旦一个共享变量(类的成员变量.类的静态成员变量)被volatile修饰之后,那么就具备了两层语义: 1)保证了不同线程对这个变量进行操作时的可见性,即一个线程修改了 ...
- Java并发编程1--synchronized关键字用法详解
1.synchronized的作用 首先synchronized可以修饰方法或代码块,可以保证同一时刻只有一个线程可以执行这个方法或代码块,从而达到同步的效果,同时可以保证共享变量的内存可见性 2.s ...
- Java并发编程volatile关键字
volatile理解 Java语言是支持多线程的,为了解决线程并发的问题,在语言内部引入了 同步块 和volatile 关键字机制.volatile具有synchronized关键字的“可见性”,vo ...
- java并发编程 volatile关键字 精准理解
1.volatile的作用 一个线程共享变量(类的成员变量.类的静态成员变量等)被volatile修饰之后,就具有以下作用: 1)并发中的变量可见性(不同线程对该变量进行操作时的可见性),即一个线程修 ...
- Java并发编程:volatile关键字解析
Java并发编程:volatile关键字解析 volatile这个关键字可能很多朋友都听说过,或许也都用过.在Java 5之前,它是一个备受争议的关键字,因为在程序中使用它往往会导致出人意料的结果.在 ...
- (转)Java并发编程:volatile关键字解析
转:http://www.cnblogs.com/dolphin0520/p/3920373.html Java并发编程:volatile关键字解析 volatile这个关键字可能很多朋友都听说过,或 ...
- Java并发编程:volatile关键字解析(转载)
转自https://www.cnblogs.com/dolphin0520/p/3920373.html Java并发编程:volatile关键字解析 Java并发编程:volatile关键字解析 ...
- Java并发编程学习:volatile关键字解析
转载:https://www.cnblogs.com/dolphin0520/p/3920373.html 写的非常棒,好东西要分享一下 Java并发编程:volatile关键字解析 volatile ...
随机推荐
- lua --- 用break实现continue逻辑
循环中内嵌一个循环,然后将具体的逻辑放在内嵌循环中去处理,在内嵌循环的开始,添加一个判断语句,满足条件就跳出内嵌循环. 示例代码如下: tab = {,,,,} ,#tab do while true ...
- legend2---开发日志6(后端和前端如何相互配合(比如php,js,元素状态和数据改变))
legend2---开发日志6(后端和前端如何相互配合(比如php,js,元素状态和数据改变)) 一.总结 一句话总结:php给元素初始状态,js根据这个状态做初始化和后续变化,使用vue真的很方便( ...
- go 圣经阅读笔记之-入门
go 圣经 这本书英文名为 <The Go Programming Language> 1. 简单hello world示例 helloworld.go package main impo ...
- InitializingBean和DisposableBean
InitializingBean 记住一点:InitializingBean接口为bean提供了初始化方法的方式,它只包括afterPropertiesSet方法,凡是继承该接口的子类,在初始化bea ...
- 雷林鹏分享:jQuery EasyUI 树形菜单 - 树形菜单加载父/子节点
jQuery EasyUI 树形菜单 - 树形菜单加载父/子节点 通常表示一个树节点的方式就是在每一个节点存储一个 parentid. 这个也被称为邻接列表模型. 直接加载这些数据到树形菜单(Tree ...
- java.lang.NoClassDefFoundError: org/hibernate/cfg/Configuration
java.lang.NoClassDefFoundError: org/hibernate/cfg/Configuration 最近在做项目的时候遇到了这个问题,很是困扰,多次尝试后发现是jar包的问 ...
- 【IOS学习】【Swift语言】
基本语法: OS X playground 引入 import Cocoa IOS playground 引入 import UIKit 基本数据类型 let 定义常量 定义完成之后无法修改 var ...
- vue 点击一个div,使input获得焦点
<div class="inputMessage" @click="inputMessage">输入留言</div> <input ...
- lanmp中环境变量的更改方法
1.vim /etc/profile 改成: export PATH=$PATH:/www/wdlinux/phps/71/bin/ 然后运行: source /etc/profile
- 03 爬虫之selenium模块
selenium模块 1.概念,了解selenium 什么是selenium?selenium是Python的一个第三方库,对外提供的接口可以操作浏览器,然后让浏览器完成自动化的操作. seleniu ...