java基础知识回顾之java Thread类学习(六)--java多线程同步函数用的锁
1.验证同步函数使用的锁----普通方法使用的锁
- 思路:创建两个线程,同时操作同一个资源,还是用卖票的例子来验证。创建好两个线程t1,t2,t1线程走同步代码块操作tickets,t2,线程走同步函数封装的代码操作tickets,同步代码块中的锁我们可以指定。假设我们事先不知道同步函数用的是什么锁;如果在同步代码块中指定的某个锁(测试)和同步函数用的锁相同,就不会出现线程安全问题,如果锁不相同,就会发生线程安全问题。
看下面的代码:t1线程用的同步锁是obj,t2线程在操作同步函数的资源,假设不知道用的是什么锁?我们测试代码,看是否会发生线程安全问题。
public class TestMethodSynchronisedLock implements Runnable {
private int tickets = 100;
private boolean flag = true;
Object obj = new Object();
@Override
public void run() {
// TODO Auto-generated method stub
if(flag){//标志位true,t1进入同步代码块
while (true){
synchronized (obj) {
if(tickets > 0){
try {
Thread.sleep(100);
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
System.out.println(Thread.currentThread().getName()+">>>>obj<<<<<"+(tickets--));
}
}
}
}else{
while(true){this.show();} }
} public synchronized void show(){//同步函数
while (true){
if(tickets > 0){ System.out.println(Thread.currentThread().getName()+">>>>show<<<<<"+(tickets--));
}
}
}
public static void main(String[]args){
TestMethodSynchronisedLock r = new TestMethodSynchronisedLock();
Thread t1 = new Thread(r);
Thread t2 = new Thread(r);
t1.start();//t1启动之后进入同步代码块
try {
Thread.sleep(100);//主线程开启完t1,停了10毫秒,避免执行的太快,t2线程进入不了函数
} catch (InterruptedException e) {
e.printStackTrace();
}
r.flag = false;//标记切换
t2.start();//t2线程进入同步函数执行代码
}
}
运行结果:
Thread-1>>>>show<<<<<100
Thread-1>>>>show<<<<<99
Thread-1>>>>show<<<<<98
Thread-1>>>>show<<<<<97
Thread-1>>>>show<<<<<96
Thread-1>>>>show<<<<<95
Thread-1>>>>show<<<<<94
Thread-1>>>>show<<<<<93
Thread-1>>>>show<<<<<92
Thread-1>>>>show<<<<<91
Thread-1>>>>show<<<<<90
Thread-0>>>>obj<<<<<88
Thread-1>>>>show<<<<<89
Thread-1>>>>show<<<<<87
Thread-1>>>>show<<<<<86
Thread-1>>>>show<<<<<85
Thread-1>>>>show<<<<<84
Thread-1>>>>show<<<<<83
Thread-1>>>>show<<<<<82
Thread-1>>>>show<<<<<81
Thread-1>>>>show<<<<<80
Thread-1>>>>show<<<<<79
Thread-1>>>>show<<<<<78
Thread-1>>>>show<<<<<77
Thread-1>>>>show<<<<<76
Thread-1>>>>show<<<<<75
Thread-1>>>>show<<<<<74
Thread-1>>>>show<<<<<73
Thread-1>>>>show<<<<<72
Thread-1>>>>show<<<<<71
Thread-1>>>>show<<<<<70
Thread-1>>>>show<<<<<69
Thread-1>>>>show<<<<<68
Thread-1>>>>show<<<<<67
Thread-1>>>>show<<<<<66
Thread-1>>>>show<<<<<65
Thread-1>>>>show<<<<<64
Thread-1>>>>show<<<<<63
Thread-1>>>>show<<<<<62
Thread-1>>>>show<<<<<61
Thread-1>>>>show<<<<<60
Thread-1>>>>show<<<<<59
Thread-1>>>>show<<<<<58
Thread-1>>>>show<<<<<57
Thread-1>>>>show<<<<<56
Thread-1>>>>show<<<<<55
Thread-1>>>>show<<<<<54
Thread-1>>>>show<<<<<53
Thread-1>>>>show<<<<<52
Thread-1>>>>show<<<<<51
Thread-1>>>>show<<<<<50
Thread-1>>>>show<<<<<49
Thread-1>>>>show<<<<<48
Thread-1>>>>show<<<<<47
Thread-1>>>>show<<<<<46
Thread-1>>>>show<<<<<45
Thread-1>>>>show<<<<<44
Thread-1>>>>show<<<<<43
Thread-1>>>>show<<<<<42
Thread-1>>>>show<<<<<41
Thread-1>>>>show<<<<<40
Thread-1>>>>show<<<<<39
Thread-1>>>>show<<<<<38
Thread-1>>>>show<<<<<37
Thread-1>>>>show<<<<<36
Thread-1>>>>show<<<<<35
Thread-1>>>>show<<<<<34
Thread-1>>>>show<<<<<33
Thread-1>>>>show<<<<<32
Thread-1>>>>show<<<<<31
Thread-1>>>>show<<<<<30
Thread-1>>>>show<<<<<29
Thread-1>>>>show<<<<<28
Thread-1>>>>show<<<<<27
Thread-1>>>>show<<<<<26
Thread-1>>>>show<<<<<25
Thread-1>>>>show<<<<<24
Thread-1>>>>show<<<<<23
Thread-1>>>>show<<<<<22
Thread-1>>>>show<<<<<21
Thread-1>>>>show<<<<<20
Thread-1>>>>show<<<<<19
Thread-1>>>>show<<<<<18
Thread-1>>>>show<<<<<17
Thread-1>>>>show<<<<<16
Thread-1>>>>show<<<<<15
Thread-1>>>>show<<<<<14
Thread-1>>>>show<<<<<13
Thread-1>>>>show<<<<<12
Thread-1>>>>show<<<<<11
Thread-1>>>>show<<<<<10
Thread-1>>>>show<<<<<9
Thread-1>>>>show<<<<<8
Thread-1>>>>show<<<<<7
Thread-1>>>>show<<<<<6
Thread-1>>>>show<<<<<5
Thread-1>>>>show<<<<<4
Thread-1>>>>show<<<<<3
Thread-1>>>>show<<<<<2
Thread-1>>>>show<<<<<1
Thread-0>>>>obj<<<<<0
出现了0票,出现了线程安全问题。t1和t2不是用的同一个锁,说明同步函数不是用的obj锁。
把上面同步代码块的锁换成this,在进行测试。
package com.lp.ecjtu.Thread;
public class TestMethodSynchronisedLock implements Runnable {
private int tickets = 100;
private boolean flag = true;
//Object obj = new Object();
@Override
public void run() {
// TODO Auto-generated method stub
if(flag){//标志位true,t1进入同步代码块
while (true){
synchronized (this) {//同步代码块,obj改为this证明同步代码块和下面的同步函数调用的是this锁
if(tickets > 0){
try {
Thread.sleep(100);
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
System.out.println(Thread.currentThread().getName()+">>>>obj<<<<<"+(tickets--));
}
}
}
}else{
while(true){this.show();} }
} public synchronized void show(){//同步函数
while (true){
if(tickets > 0){ System.out.println(Thread.currentThread().getName()+">>>>show<<<<<"+(tickets--));
}
}
}
public static void main(String[]args){
TestMethodSynchronisedLock r = new TestMethodSynchronisedLock();
Thread t1 = new Thread(r);
Thread t2 = new Thread(r);
t1.start();//t1启动之后进入同步代码块
try {
Thread.sleep(100);//主线程开启完t1,停了10毫秒,避免执行的太快,t1线程进入不了synchronized代码块
} catch (InterruptedException e) {
e.printStackTrace();
}
r.flag = false;//标记切换
t2.start();//2线程进入同步函数代码块
}
}
运行结果如下:
Thread-0>>>>obj<<<<<100
Thread-0>>>>obj<<<<<99
Thread-0>>>>obj<<<<<98
Thread-1>>>>show<<<<<97
Thread-1>>>>show<<<<<96
Thread-1>>>>show<<<<<95
Thread-1>>>>show<<<<<94
Thread-1>>>>show<<<<<93
Thread-1>>>>show<<<<<92
Thread-1>>>>show<<<<<91
Thread-1>>>>show<<<<<90
Thread-1>>>>show<<<<<89
Thread-1>>>>show<<<<<88
Thread-1>>>>show<<<<<87
Thread-1>>>>show<<<<<86
Thread-1>>>>show<<<<<85
Thread-1>>>>show<<<<<84
Thread-1>>>>show<<<<<83
Thread-1>>>>show<<<<<82
Thread-1>>>>show<<<<<81
Thread-1>>>>show<<<<<80
Thread-1>>>>show<<<<<79
Thread-1>>>>show<<<<<78
Thread-1>>>>show<<<<<77
Thread-1>>>>show<<<<<76
Thread-1>>>>show<<<<<75
Thread-1>>>>show<<<<<74
Thread-1>>>>show<<<<<73
Thread-1>>>>show<<<<<72
Thread-1>>>>show<<<<<71
Thread-1>>>>show<<<<<70
Thread-1>>>>show<<<<<69
Thread-1>>>>show<<<<<68
Thread-1>>>>show<<<<<67
Thread-1>>>>show<<<<<66
Thread-1>>>>show<<<<<65
Thread-1>>>>show<<<<<64
Thread-1>>>>show<<<<<63
Thread-1>>>>show<<<<<62
Thread-1>>>>show<<<<<61
Thread-1>>>>show<<<<<60
Thread-1>>>>show<<<<<59
Thread-1>>>>show<<<<<58
Thread-1>>>>show<<<<<57
Thread-1>>>>show<<<<<56
Thread-1>>>>show<<<<<55
Thread-1>>>>show<<<<<54
Thread-1>>>>show<<<<<53
Thread-1>>>>show<<<<<52
Thread-1>>>>show<<<<<51
Thread-1>>>>show<<<<<50
Thread-1>>>>show<<<<<49
Thread-1>>>>show<<<<<48
Thread-1>>>>show<<<<<47
Thread-1>>>>show<<<<<46
Thread-1>>>>show<<<<<45
Thread-1>>>>show<<<<<44
Thread-1>>>>show<<<<<43
Thread-1>>>>show<<<<<42
Thread-1>>>>show<<<<<41
Thread-1>>>>show<<<<<40
Thread-1>>>>show<<<<<39
Thread-1>>>>show<<<<<38
Thread-1>>>>show<<<<<37
Thread-1>>>>show<<<<<36
Thread-1>>>>show<<<<<35
Thread-1>>>>show<<<<<34
Thread-1>>>>show<<<<<33
Thread-1>>>>show<<<<<32
Thread-1>>>>show<<<<<31
Thread-1>>>>show<<<<<30
Thread-1>>>>show<<<<<29
Thread-1>>>>show<<<<<28
Thread-1>>>>show<<<<<27
Thread-1>>>>show<<<<<26
Thread-1>>>>show<<<<<25
Thread-1>>>>show<<<<<24
Thread-1>>>>show<<<<<23
Thread-1>>>>show<<<<<22
Thread-1>>>>show<<<<<21
Thread-1>>>>show<<<<<20
Thread-1>>>>show<<<<<19
Thread-1>>>>show<<<<<18
Thread-1>>>>show<<<<<17
Thread-1>>>>show<<<<<16
Thread-1>>>>show<<<<<15
Thread-1>>>>show<<<<<14
Thread-1>>>>show<<<<<13
Thread-1>>>>show<<<<<12
Thread-1>>>>show<<<<<11
Thread-1>>>>show<<<<<10
Thread-1>>>>show<<<<<9
Thread-1>>>>show<<<<<8
Thread-1>>>>show<<<<<7
Thread-1>>>>show<<<<<6
Thread-1>>>>show<<<<<5
Thread-1>>>>show<<<<<4
Thread-1>>>>show<<<<<3
Thread-1>>>>show<<<<<2
Thread-1>>>>show<<<<<1
多次运行分析,线程安全,说明同步代码块和同步函数运行的锁是一样的。总结:函数被对象引用,那么函数都一个所属对象的引用,就是this,所以同步函数使用的锁是this。
2.验证同步函数使用的锁----静态方法使用的锁
思路和上面验证普通方法的思路一样。直接给出结论:
静态方法使用的锁是该方法所在的类的字节码文件对象( 类名.class)
* 通过验证,发现不是this,因为静态方法中不可以定义this
* 静态变量存放在内存共享区域内,而对象是存放在堆内存中。
* 静态进内存时,内存中没有本类对象,但是一定有该类对应的字节码的文件对象。
* 类名.class
public class TestStaticMethodSynchronisedLock implements Runnable {
private static int tickets = 100;
private boolean flag = true;
@Override
public void run() {
// TODO Auto-generated method stub
if(flag){
while (true){
synchronized (TestStaticMethodSynchronisedLock.class) {//静态方法用的锁是类字节码文件对象(类.class)
if(tickets > 0){
try {
Thread.sleep(100);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println(Thread.currentThread().getName()+">>>>code<<<<<"+(tickets--));
}
}
}
}else{
while(true){this.show();} }
} public static synchronized void show(){//同步函数
while (true){
if(tickets > 0){
System.out.println(Thread.currentThread().getName()+">>>>show<<<<<"+(tickets--));
}
}
}
public static void main(String[]args){
TestStaticMethodSynchronisedLock r = new TestStaticMethodSynchronisedLock();
Thread t1 = new Thread(r);
Thread t2 = new Thread(r);
t1.start();
try {
Thread.sleep(100);//主线程停了10毫秒,避免执行的太快,t1线程进入不了synchronized代码块
} catch (InterruptedException e) {
e.printStackTrace();
}
r.flag = false;
t2.start();
}
}
运行结果,是线程安全的。
java基础知识回顾之java Thread类学习(六)--java多线程同步函数用的锁的更多相关文章
- java基础知识回顾之---java String final类普通方法
辞职了,最近一段时间在找工作,把在大二的时候学习java基础知识回顾下,拿出来跟大家分享,如果有问题,欢迎大家的指正. /* * 按照面向对象的思想对字符串进行功能分类. * ...
- Java基础知识回顾之七 ----- 总结篇
前言 在之前Java基础知识回顾中,我们回顾了基础数据类型.修饰符和String.三大特性.集合.多线程和IO.本篇文章则对之前学过的知识进行总结.除了简单的复习之外,还会增加一些相应的理解. 基础数 ...
- Java基础-进程与线程之Thread类详解
Java基础-进程与线程之Thread类详解 作者:尹正杰 版权声明:原创作品,谢绝转载!否则将追究法律责任. 一.进程与线程的区别 简而言之:一个程序运行后至少有一个进程,一个进程中可以包含多个线程 ...
- java基础知识回顾之java Thread类学习(五)--java多线程安全问题(锁)同步的前提
这里举个例子讲解,同步synchronized在什么地方加,以及同步的前提: * 1.必须要有两个以上的线程,才需要同步. * 2.必须是多个线程使用同一个锁. * 3.必须保证同步中只能有一个线程在 ...
- Java基础知识回顾(一):字符串小结
Java的基础知识回顾之字符串 一.引言 很多人喜欢在前面加入赘述,事实上去技术网站找相关的内容的一般都应当已经对相应知识有一定了解,因此我不再过多赘述字符串到底是什么东西,在官网中已经写得很明确了, ...
- java基础知识回顾之java Thread类学习(三)--java线程实现常见的两种方式实现好处:
总结:实现Runnable接口比继承Thread类更有优势: 1.因为java只能单继承,实现Runnable接口可以避免单继承的局限性 2.继承Thread类,多个线程不能处理或者共享同一个资源,但 ...
- java基础知识回顾之java Thread类学习(七)--java多线程通信等待唤醒机制(wait和notify,notifyAll)
1.wait和notify,notifyAll: wait和notify,notifyAll是Object类方法,因为等待和唤醒必须是同一个锁,不可以对不同锁中的线程进行唤醒,而锁可以是任意对象,所以 ...
- java基础知识回顾之java Thread类--java线程实现常见的两种方式实现Runnable接口(二)
创建线程的第二中方式: /** * 步骤: 1定义类实现Runnable接口 2.实现Runnable接口中的run方法. 3.通过Thread类建立线程对象,并将Run ...
- java基础知识回顾之java Thread类学习(七)--java多线程安全问题(死锁)
死锁:是两个或者两个以上的线程被无限的阻塞,线程之间互相等待所需资源. 线程死锁产生的条件: 当两个线程相互调用Join()方法. 当两个线程使用嵌套的同步代码块的时候,一个线程占用了另一个线程的锁, ...
随机推荐
- Linux 输入子系统
Technorati 标签: Kernel 输入子系统 Input 在Linux中,输入设备(如按键.键盘.触摸屏.鼠标等)是典型的字符设备,其一般的工作机理,是底层在按键.触摸时,触发一个 ...
- easyUI中treegrid组件构造树形表格(简单数据类型)+ssm后台
这几天做的项目要求用树形表格的形式展示一部分数据,于是就想到了使用easyUI的treegrid组件,但几经翻查各种资料,发现数据类型大多采取标准数据类型,即包含children元素的数据类型,小编查 ...
- 实现textarea自适应的方法
1.用div来模拟实现textarea自适应 <!doctype html> <html lang="en"> <head> <meta ...
- c# 分页控件
因为最近做的培训项目需要用到很多分页功能,自己写了一个分页方法,想找个时间重构,看到一篇博客,转载过来,分享学习. 原文链接:http://www.cnblogs.com/rr163/p/395593 ...
- jquery批量控制form禁用的代码
jquery批量控制form禁用的代码. 代码: <script type="text/javascript" src="/jquery/jquery-1.8.2. ...
- webstorm 10.0.4 注册码
激活码: UserName:William ===== LICENSE BEGIN ===== 45550-12042010 00001SzFN0n1bPII7FnAxnt0DDOPJA INauvJ ...
- DataSnap中连接池的应用
当开发人员开始创建Delphi的DataSnap应用时很常见的数据库连接定义方式是每个数据模块建立一个连接.这样做将产生大量的数据库连接,并产生很多问题.从Delphi XE开始,EMB提供了Sess ...
- php正则表达式判断是否为ip格式
<?php $a = '127.0.0.111'; $b = preg_match("/^\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3}$/",$a); ...
- CP="CAO PSA OUR" 用P3P header解决iframe跨域访问cookie
1.IE浏览器iframe跨域丢失Session问题 在开发中,我们经常会遇到使用Frame来工作,而且有时是为了跟其他网站集成,应用到多域的情况下,而Iframe是不能保存Session的因此,网上 ...
- DBA应该知道的一些SQL Server跟踪标记
跟踪标记是什么? 对于DBA来说,掌握Trace Flag是一个成为SQL Server高手的必要条件之一,在大多数情况下,Trace Flag只是一个剑走偏锋的奇招,不必要,但在很多情况下,会使用这 ...