java并发编程实践学习---java的类锁和对象锁
来源:互联网 发布:炉石传说淘宝买卡包 编辑:程序博客网 时间:2024/04/30 11:02
最近在看Java Concurrent in Practice(java并发编程实践),发现自己对java的线程、锁等机制,理解很肤浅,学习的也不够全面。打算借着这本书,全面的学习下JDK的并发包和一些线程相关的理论知识,填补自己的空白,也可以和大家交流,理解不正确的地方,欢迎指正。第一篇博客,先简单的介绍下类锁和对象锁的概念,和关键字synchronized。
对象锁:java的所有对象都含有1个互斥锁,这个锁由JVM自动获取和释放。线程进入synchronized方法的时候获取该对象的锁,当然如果已经有线程获取了这个对象的锁,那么当前线程会等待;synchronized方法正常返回或者抛异常而终止,JVM会自动释放对象锁。这里也体现了用synchronized来加锁的1个好处,方法抛异常的时候,锁仍然可以由JVM来自动释放。
类锁:对象锁是用来控制实例方法之间的同步,类锁是用来控制静态方法(或静态变量互斥体)之间的同步。其实类锁只是一个概念上的东西,并不是真实存在的,它只是用来帮助我们理解锁定实例方法和静态方法的区别的。我们都知道,java类可能会有很多个对象,但是只有1个Class对象,也就是说类的不同实例之间共享该类的Class对象。Class对象其实也仅仅是1个java对象,只不过有点特殊而已。由于每个java对象都有1个互斥锁,而类的静态方法是需要Class对象。所以所谓的类锁,不过是Class对象的锁而已。获取类的Class对象有好几种,最简单的就是MyClass.class的方式。
为什么需要加锁呢?肯定是因为存在不同线程对共享对象的并发访问,没有数据共享就不需要锁。
下面这个类,是我们使用java的synchronized方式进行控制的方法,会在我们后面的线程中调用。
package
net.aty.lock.target;
public
class
TargetMethod
{
// 对象锁:形式1
public
synchronized
void
objLockMethod1()
{
System.out.println(
"in...objLockMethod1"
);
try
{
Thread.sleep(
500
);
}
catch
(InterruptedException e)
{
e.printStackTrace();
}
System.out.println(
"out...objLockMethod1"
);
}
// 对象锁:形式2
public
void
objLockMethod2()
{
synchronized
(
this
)
{
System.out.println(
"in...objLockMethod2"
);
try
{
Thread.sleep(
500
);
}
catch
(InterruptedException e)
{
e.printStackTrace();
}
System.out.println(
"out...objLockMethod2"
);
}
}
// 类锁:形式1
public
static
synchronized
void
classLock1()
{
System.out.println(
"classLock1------in"
);
try
{
Thread.sleep(
500
);
}
catch
(InterruptedException e)
{
e.printStackTrace();
}
System.out.println(
"classLock1------out"
);
}
// 类锁:形式2
public
void
classLock2()
{
synchronized
(TargetMethod.
class
)
{
System.out.println(
"classLock2------in"
);
try
{
Thread.sleep(
500
);
}
catch
(InterruptedException e)
{
e.printStackTrace();
}
System.out.println(
"classLock2------out"
);
}
}
}
1、我们先来做第一个测试,该测试很简单,说明:如果线程不存在数据共享,锁就不会有效果,也就没有必要加锁。
package
net.aty.lock.thread.first;
import
net.aty.lock.target.TargetMethod;
public
class
DemoThread1
extends
Thread
{
private
TargetMethod target =
null
;
public
DemoThread1(TargetMethod target)
{
this
.target = target;
}
@Override
public
void
run()
{
target.objLockMethod1();
}
}
package
net.aty.lock.thread.first;
import
net.aty.lock.target.TargetMethod;
public
class
DemoThread2
extends
Thread
{
private
TargetMethod target =
null
;
public
DemoThread2(TargetMethod target)
{
this
.target = target;
}
@Override
public
void
run()
{
target.objLockMethod2();
}
}
package
net.aty.lock.thread.first;
import
net.aty.lock.target.TargetMethod;
public
class
Test
{
public
static
void
main(String[] args)
throws
Exception
{
test2();
}
public
static
void
test1()
throws
Exception
{
TargetMethod target1 =
new
TargetMethod();
TargetMethod target2 =
new
TargetMethod();
// 线程1运行后,睡眠500ms
Thread t1 =
new
DemoThread1(target1);
t1.start();
// 主线程睡眠100ms后,恢复执行,此时线程1仍然处于睡眠状态
Thread.sleep(
100
);
System.out.println(
"main thread runnig...."
);
// 线程2开始运行
Thread t2 =
new
DemoThread2(target2);
t2.start();
}
public
static
void
test2()
throws
Exception
{
TargetMethod shared =
new
TargetMethod();
Thread t1 =
new
DemoThread1(shared);
t1.start();
Thread.sleep(
100
);
System.out.println(
"main thread runnig...."
);
Thread t2 =
new
DemoThread2(shared);
t2.start();
}
}
package
net.aty.lock.thread.second;
import
net.aty.lock.target.TargetMethod;
public
class
DemoThread3
extends
Thread
{
public
DemoThread3()
{
}
@Override
public
void
run()
{
TargetMethod.classLock1();
}
}
package
net.aty.lock.thread.second;
import
net.aty.lock.target.TargetMethod;
public
class
DemoThread4
extends
Thread
{
private
TargetMethod target =
null
;
public
DemoThread4(TargetMethod target)
{
this
.target = target;
}
@Override
public
void
run()
{
target.classLock2();
}
}
package
net.aty.lock.thread.second;
import
net.aty.lock.target.TargetMethod;
public
class
Test
{
public
static
void
main(String[] args)
throws
Exception
{
// 线程3运行后,睡眠500ms
Thread t1 =
new
DemoThread3();
t1.start();
// 主线程睡眠100ms后,恢复执行,此时线程1仍然处于睡眠状态
Thread.sleep(
100
);
System.out.println(
"main thread runnig...."
);
// 线程4开始运行
Thread t2 =
new
DemoThread4(
new
TargetMethod());
t2.start();
}
}
执行结果如下:通过分析,可以知道的确实现了static方法之间的同步访问
classLock1------in
main thread runnig....
classLock1------out
classLock2------in
classLock2------out
3、最后我们来测试下对象锁和类锁的区别和联系。线程5会访问同步的实例方法,线程6访问同步的静态方法。
package
net.aty.lock.thread.third;
import
net.aty.lock.target.TargetMethod;
public
class
DemoThread5
extends
Thread
{
private
TargetMethod target =
null
;
public
DemoThread5(TargetMethod target)
{
this
.target = target;
}
@Override
public
void
run()
{
target.objLockMethod1();
}
}
package
net.aty.lock.thread.third;
import
net.aty.lock.target.TargetMethod;
public
class
DemoThread6
extends
Thread
{
public
DemoThread6()
{
}
@Override
public
void
run()
{
TargetMethod.classLock1();
}
}
package
net.aty.lock.thread.third;
import
net.aty.lock.target.TargetMethod;
public
class
Test
{
public
static
void
main(String[] args)
throws
Exception
{
test2();
}
public
static
void
test1()
throws
Exception
{
// 线程5开始运行
Thread t1 =
new
DemoThread5(
new
TargetMethod());
t1.start();
// 主线程睡眠100ms后,恢复执行,此时线程1仍然处于睡眠状态
Thread.sleep(
100
);
System.out.println(
"main thread runnig...."
);
// 线程6运行后,睡眠500ms
Thread t2 =
new
DemoThread6();
t2.start();
}
public
static
void
test2()
throws
Exception
{
// 线程6开始运行
Thread t2 =
new
DemoThread6();
t2.start();
// 主线程睡眠100ms后,恢复执行,此时线程1仍然处于睡眠状态
Thread.sleep(
100
);
System.out.println(
"main thread runnig...."
);
// 线程5
Thread t1 =
new
DemoThread5(
new
TargetMethod());
t1.start();
}
}
执行结果如下:
classLock1------in
main thread runnig....
in...objLockMethod1
classLock1------out
out...objLockMethod1
可以看出,类锁和对象锁不是同1个东西,一个是类的Class对象的锁,1个是类的实例的锁。也就是说:1个线程访问静态synchronized的时候,允许另一个线程访问对象的实例synchronized方法。反过来也是成立的,因为他们需要的锁是不同的。
- java并发编程实践学习(一)java的类锁和对象锁
- java并发编程实践学习---java的类锁和对象锁
- java并发编程实践学习(2)--对象的组合
- java并发编程实践学习(四)对象的发布和逸出之this逃逸
- java并发编程实践学习
- Java并发编程---对象锁的同步和异步
- java并发编程实践学习(2)共享对象
- java并发编程实践学习(2)共享对象
- java并发编程实践学习(3)组合对象
- java并发编程实践之共享对象学习笔记
- 【Java并发编程实践】线程安全性、对象的共享和对象的组合
- java并发编程实践学习(13 ) 显示锁
- java并发编程实践之对象的共享
- <Java 并发编程实践>读书笔记 --- 内部锁
- java并发编程实践学习(7) 取消和关闭
- [Java 并发] Java并发编程实践 思维导图 - 第三章 对象的共享
- [Java 并发] Java并发编程实践 思维导图 - 第四章 对象的组合
- java并发编程实践学习笔记
- Android 多点touch触控事件传递
- React-Native系列Android——Native与Javascript通信原理(三)
- QMenu的个性化定制
- 诺亚方舟实验室李航:深度学习还局限在复杂的模式识别上
- 理解DrawerLayout抽屉
- java并发编程实践学习---java的类锁和对象锁
- web.xml 配置中classpath: 与classpath*:的区别
- 黑盒测试的几个实测试设计
- 自己写个AsyncTask
- 基于大数据与深度学习的自然语言对话
- 北京fh项目总结1
- 16-4SUM
- C语言计算字符串长度的几种方法
- ubuntu桌面快捷方式文件内容