- ubuntu12.04环境下使用kvm ioctl接口实现最简单的虚拟机
- Ubuntu 通过无线网络安装Ubuntu Server启动系统后连接无线网络的方法
- 在Ubuntu上搭建网桥的方法
- ubuntu 虚拟机上网方式及相关配置详解
CFSDN坚持开源创造价值,我们致力于搭建一个资源共享平台,让每一个IT人在这里找到属于你的精彩世界.
这篇CFSDN的博客文章Java Synchronized的使用详解由作者收集整理,如果你对这篇文章有兴趣,记得点赞哟.
1.为什么要使用synchronized 。
在并发编程中存在线程安全问题,主要原因有:1.存在共享数据 2.多线程共同操作共享数据。关键字synchronized可以保证在同一时刻,只有一个线程可以执行某个方法或某个代码块,同时synchronized可以保证一个线程的变化可见(可见性),即可以代替volatile.
2.实现原理 。
synchronized可以保证方法或者代码块在运行时,同一时刻只有一个方法可以进入到临界区,同时它还可以保证共享变量的内存可见性 。
3.synchronized的三种应用方式 。
Java中每一个对象都可以作为锁,这是synchronized实现同步的基础:
普通同步方法(实例方法),锁是当前实例对象 ,进入同步代码前要获得当前实例的锁静态同步方法,锁是当前类的class对象 ,进入同步代码前要获得当前类对象的锁同步方法块,锁是括号里面的对象,对给定对象加锁,进入同步代码库前要获得给定对象的锁.
4.synchronized的作用 。
Synchronized是Java中解决并发问题的一种最常用最简单的方法 ,他可以确保线程互斥的访问同步代码 。
5.举栗子 。
**1、synchronized作用于实例方法** 。
①多个线程访问同一个对象的同一个方法 。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
|
public
class
synchronizedTest
implements
Runnable {
//共享资源
static
int
i =
0
;
/**
* synchronized 修饰实例方法
*/
public
synchronized
void
increase(){
i++;
}
@Override
public
void
run(){
for
(
int
j =
0
; j<
10000
;j++){
increase();
}
}
public
static
void
main(String[] args)
throws
InterruptedException {
synchronizedTest test =
new
synchronizedTest();
Thread t1 =
new
Thread(test);
Thread t2 =
new
Thread(test);
t1.start();
t2.start();
t1.join();
t2.join();
System.out.println(i);
}
}
|
结果:
分析:当两个线程同时对一个对象的一个方法进行操作,只有一个线程能够抢到锁。因为一个对象只有一把锁,一个线程获取了该对象的锁之后,其他线程无法获取该对象的锁,就不能访问该对象的其他synchronized实例方法,但是可以访问非synchronized修饰的方法 。
②一个线程获取了该对象的锁之后,其他线程来访问其他synchronized实例方法现象 举栗 。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
|
public
class
SynchronizedTest {
public
synchronized
void
method1() {
System.out.println(
"Method 1 start"
);
try
{
System.out.println(
"Method 1 execute"
);
Thread.sleep(
3000
);
}
catch
(InterruptedException e) {
e.printStackTrace();
}
System.out.println(
"Method 1 end"
);
}
public
synchronized
void
method2() {
System.out.println(
"Method 2 start"
);
try
{
System.out.println(
"Method 2 execute"
);
Thread.sleep(
1000
);
}
catch
(InterruptedException e) {
e.printStackTrace();
}
System.out.println(
"Method 2 end"
);
}
public
static
void
main(String[] args) {
final
SynchronizedTest test =
new
SynchronizedTest();
new
Thread(test::method1).start();
new
Thread(test::method2).start();
}
}
|
结果:
分析:可以看出其他线程来访问synchronized修饰的其他方法时需要等待线程1先把锁释放 。
③一个线程获取了该对象的锁之后,其他线程来访问其他非synchronized实例方法现象 举栗 去掉②中方法二的synchronized 。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
|
public
class
SynchronizedTest {
public
synchronized
void
method1() {
System.out.println(
"Method 1 start"
);
try
{
System.out.println(
"Method 1 execute"
);
Thread.sleep(
3000
);
}
catch
(InterruptedException e) {
e.printStackTrace();
}
System.out.println(
"Method 1 end"
);
}
public
void
method2() {
System.out.println(
"Method 2 start"
);
try
{
System.out.println(
"Method 2 execute"
);
Thread.sleep(
1000
);
}
catch
(InterruptedException e) {
e.printStackTrace();
}
System.out.println(
"Method 2 end"
);
}
public
static
void
main(String[] args) {
final
SynchronizedTest test =
new
SynchronizedTest();
new
Thread(test::method1).start();
new
Thread(test::method2).start();
}
}
|
结果:
分析:当线程1还在执行时,线程2也执行了,所以当其他线程来访问非synchronized修饰的方法时是可以访问的 。
④当多个线程作用于不同的对象 。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
|
public
class
SynchronizedTest {
public
synchronized
void
method1() {
System.out.println(
"Method 1 start"
);
try
{
System.out.println(
"Method 1 execute"
);
Thread.sleep(
3000
);
}
catch
(InterruptedException e) {
e.printStackTrace();
}
System.out.println(
"Method 1 end"
);
}
public
synchronized
void
method2() {
System.out.println(
"Method 2 start"
);
try
{
System.out.println(
"Method 2 execute"
);
Thread.sleep(
1000
);
}
catch
(InterruptedException e) {
e.printStackTrace();
}
System.out.println(
"Method 2 end"
);
}
public
static
void
main(String[] args) {
final
SynchronizedTest test1 =
new
SynchronizedTest();
final
SynchronizedTest test2 =
new
SynchronizedTest();
new
Thread(test1::method1).start();
new
Thread(test2::method2).start();
}
}
|
结果:
分析:因为两个线程作用于不同的对象,获得的是不同的锁,所以互相并不影响 。
**此处思考一个问题:为什么分布式环境下synchronized失效?如何解决这种情况?
****2、synchronized作用于静态方法** 。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
|
public
class
synchronizedTest
implements
Runnable {
//共享资源
static
int
i =
0
;
/**
* synchronized 修饰实例方法
*/
public
static
synchronized
void
increase(){
i++;
}
@Override
public
void
run(){
for
(
int
j =
0
; j<
10000
;j++){
increase();
}
}
public
static
void
main(String[] args)
throws
InterruptedException {
Thread t1 =
new
Thread(
new
synchronizedTest());
Thread t2 =
new
Thread(
new
synchronizedTest());
t1.start();
t2.start();
t1.join();
t2.join();
System.out.println(i);
}
|
结果:
分析:由例子可知,两个线程实例化两个不同的对象,但是访问的方法是静态的,两个线程发生了互斥(即一个线程访问,另一个线程只能等着),因为静态方法是依附于类而不是对象的,当synchronized修饰静态方法时,锁是class对象.
**3、synchronized作用于同步代码块** 。
为什么要同步代码块呢?在某些情况下,我们编写的方法体可能比较大,同时存在一些比较耗时的操作,而需要同步的代码又只有一小部分,如果直接对整个方法进行同步操作,可能会得不偿失,此时我们可以使用同步代码块的方式对需要同步的代码进行包裹,这样就无需对整个方法进行同步操作了.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
|
public
class
synchronizedTest
implements
Runnable {
static
synchronizedTest instance=
new
synchronizedTest();
static
int
i=
0
;
@Override
public
void
run() {
//省略其他耗时操作....
//使用同步代码块对变量i进行同步操作,锁对象为instance
synchronized
(instance){
for
(
int
j=
0
;j<
10000
;j++){
i++;
}
}
}
public
static
void
main(String[] args)
throws
InterruptedException {
Thread t1=
new
Thread(instance);
Thread t2=
new
Thread(instance);
t1.start();
t2.start();
t1.join();
t2.join();
System.out.println(i);
}
}
|
结果:
分析:将synchronized作用于一个给定的实例对象instance,即当前实例对象就是锁对象,每次当线程进入synchronized包裹的代码块时就会要求当前线程持有instance实例对象锁,如果当前有其他线程正持有该对象锁,那么新到的线程就必须等待,这样也就保证了每次只有一个线程执行i++;操作。当然除了instance作为对象外,我们还可以使用this对象(代表当前实例)或者当前类的class对象作为锁,如下代码:
1
2
3
4
5
6
7
8
9
10
11
12
13
|
//this,当前实例对象锁
synchronized
(
this
){
for
(
int
j=
0
;j<
1000000
;j++){
i++;
}
}
//class对象锁
synchronized
(AccountingSync.
class
){
for
(
int
j=
0
;j<
1000000
;j++){
i++;
}
}
|
下一篇将深入介绍Synchronized的实现原理 。
到此这篇关于Java Synchronized的使用详解的文章就介绍到这了,更多相关Java Synchronized使用内容请搜索我以前的文章或继续浏览下面的相关文章希望大家以后多多支持我! 。
原文链接:https://blog.csdn.net/zjy15203167987/article/details/82531772 。
最后此篇关于Java Synchronized的使用详解的文章就讲到这里了,如果你想了解更多关于Java Synchronized的使用详解的内容请搜索CFSDN的文章或继续浏览相关文章,希望大家以后支持我的博客! 。
在 java 中不使用“同步”关键字的情况下,是否有其他方法可以同步类或方法? 谢谢, 马利卡琼·科卡塔努尔 最佳答案 您可能想查看并发包中引入的对 JDK 5 的更改。 http://java.su
第 1 部分: 假设下面这段代码 void method1(){ synchronized (lockObject){ method2(); System.ou
我有一个 REST 服务器和一个在移动设备上运行的客户端应用程序。客户端有一些数据并希望从服务器获取数据更新。如何以 RESTful 方式在单个事务中执行此操作? 假设客户有以下元素: widge
我有一个多线程 Java 应用程序。在一种方法中,需要同步一个 ArrayList。由于 arrayList 不是线程安全的,所以我必须使用同步。问题是 ArrayList 类型的对象不是对象的成员变
我正在阅读 Android 示例中的 BluetoothChatService.java 文件,有一件事特别让我感到困惑。 方法在多个位置访问静态成员,并且定义为同步。 在另一部分中,正在访问同一个静
我知道为了实现线程安全和同步,我们使用同步块(synchronized block)或方法。 但我无法理解声明- “Java 中的同步块(synchronized block)在某些对象上同步 ” 任
在 Scala 中使用 JDBC 的示例中,有以下代码: this.synchronized { if (!driverLoaded) loadDriver() } 为什么this.synchro
abstract class A { protected abstract int isRunning(); public void concreteMethod() { synchr
有谁可以分享一下他们的经验吗?“我们什么时候在同步方法和同步块(synchronized block)之间进行调用”有任何性能问题吗? 最佳答案 When do we make a call to u
这是我之前问题的后续问题,Is this variable being safely accessed by using synchronization? 对于下面的程序, Class SubClas
我目前正在为 N 体问题实现多线程版本的 Barnes-Hut 算法。虽然该算法有效,但它不是很优化,我正在尝试减少我的程序的运行时间。 我已经确保有多个线程可以准确地找到我正在使用的空间的边界,并意
我有这门课: public class MyClass { public MyClass(){} public void actionA(){ synchronized
又是一个关于ArrayList和synchronize的问题。 我只想知道这段代码到底做了什么: ArrayList list = ....; synchronized (list) { if
我可以在另一个同步块(synchronized block)中包含同步块(synchronized block)以同步另一个对象吗? 例子: synchronized(myObjetc1){
public class ObjectCounter { private static long numOfInstances = 0; public ObjectCounter(){
我在某处读到,对于 various reasons 应该避免 synchronized(this) .然而,我遇到的一些值得尊敬的代码在构造函数中使用了以下内容: public SomeClass(C
Java 为同步代码的关键部分提供了一种非常方便的习惯用法: synchronized(someObject) { // do something really important all b
我有一个 WeakReference 的 Collections.synchronizedList,_components; 我写了类似下面的内容,希望编译者会提示: public boolean a
使用下面两个版本的Singleton Classes有什么区别 首先我使用的是synchronized(Singleton.class) 在第二个我使用同步(Obj)//第一种类型 公共(public
我正在查看 DatagramSocket 的源代码,我发现了这个: public void disconnect() { synchronized (this) { if (i
我是一名优秀的程序员,十分优秀!