黑马程序员:Java基础总结----多线程安全性&同步
2015-01-15 21:50
513 查看
Java对于多线程的安全问题提供了专业的解决方式。
同步代码块
synchronized(对象)
{
需要被同步的代码
}
对象如同锁。持有锁的线程可以在同步中执行。
没有持有锁的线程即使获取cpu的执行权,也进不去,因为没有获取锁。
火车上的卫生间---经典。
同步的前提:
1,必须要有两个或者两个以上的线程。
2,必须是多个线程使用同一个锁。
必须保证同步中只能有一个线程在运行。
好处:解决了多线程的安全问题。
弊端:多个线程需要判断锁,较为消耗资源,
同步函数
在函数上加上synchronized修饰符即可。
函数需要被对象调用。那么函数都有一个所属对象引用。就是this。
所以同步函数使用的锁是this
class
Ticket
implements
Runnable {
private
static
int
tick
= 100;
public
void
run() {
while
(tick
> 1) {
[align=left] show();[/align]
[align=left] }[/align]
[align=left] }[/align]
public
synchronized
void
show() {
try
{
Thread.
sleep(10);
}
catch
(Exception e) {
[align=left] }[/align]
// synchronized (Ticket.class) {
System.
out.println(Thread.currentThread().getName()
+
".... "
+
tick--);
//tick--;
// }
[align=left] }[/align]
[align=left]}[/align]
public
class
Ts {
public
static
void
main(String[] args) {
Ticket a =
new
Ticket();// 一个实例
new
Thread(a).start();
new
Thread(a).start();
[align=left] }[/align]
[align=left]}[/align]
需求:
银行有一个金库。
有两个储户分别存300员,每次存100,存3次
class
Bank
[align=left]{[/align]
private
int
sum
;
//Object
obj = new Object();
public
synchronized
void
add(int
n)
[align=left] {[/align]
//synchronized(obj)
//{
sum
=
sum
+ n;
try{Thread.sleep(10);}
catch(Exception e){}
System.
out.println("sum="
+sum
);
//}
[align=left] }[/align]
[align=left]}[/align]
class
Cus
implements
Runnable
[align=left]{[/align]
private
Bank
b
=
new
Bank();
public
void
run()
{
for(int
x=0; x<3; x++)
[align=left] {[/align]
b.add(100);
[align=left] }[/align]
[align=left] }[/align]
[align=left]}[/align]
class
BankDemo
[align=left]{[/align]
public
static
void
main(String[] args)
[align=left] {[/align]
Cus c =
new
Cus();
Thread t1 =
new
Thread(c);
Thread t2 =
new
Thread(c);
[align=left] t1.start();[/align]
[align=left] t2.start();[/align]
}
[align=left]}[/align]
如果同步函数被静态修饰
注意:对于static的同步函数,使用的锁不是this。是 类名.class 是该类的字节码文件对象。
涉及到了单例设计模式的懒汉式
通过验证,发现不在是this。因为静态方法中也不可以定义this。
静态进内存是,内存中没有本类对象,但是一定有该类对应的字节码文件对象。
类名.class 该对象的类型是Class
静态的同步方法,使用的锁是该方法所在类的字节码文件对象。 类名.class
public
void
run()
[align=left] {[/align]
if(flag
)
[align=left] {[/align]
while(true
)
[align=left] {[/align]
synchronized(Ticket.class)
[align=left] {[/align]
if(tick
>0)
[align=left] {[/align]
try{Thread.sleep(10);}
catch(Exception e){}
System.
out.println(Thread.currentThread().getName()+
"....code : "+
tick--);
[align=left] }[/align]
[align=left] }[/align]
[align=left] }[/align]
[align=left] }[/align]
else
while(true
)
show();
[align=left] }[/align]
public
static
synchronized
void
show()
[align=left] {[/align]
if(tick
>0)
[align=left] {[/align]
try{Thread.sleep(10);}
catch(Exception e){}
System.
out.println(Thread.currentThread().getName()+
"....show.... : "+
tick--);
[align=left] }[/align]
[align=left] }[/align]
[align=left]}[/align]
死锁。
同步中嵌套同步
死锁代码一定会写。但开发时一定注意避免
class
MyLock
[align=left]{[/align]
static
Object
locka
=
new
Object();
static
Object
lockb
=
new
Object();
[align=left]}[/align]
while(true
)
[align=left]{[/align]
synchronized(MyLock.lockb)
[align=left] {[/align]
System.out.println(Thread.currentThread().getName()+
"..else lockb");
synchronized(MyLock.locka)
[align=left] {[/align]
System.out.println(Thread.currentThread().getName()+
".....else locka");
[align=left] }[/align]
[align=left] }[/align]
[align=left]}[/align]
同步代码块
synchronized(对象)
{
需要被同步的代码
}
对象如同锁。持有锁的线程可以在同步中执行。
没有持有锁的线程即使获取cpu的执行权,也进不去,因为没有获取锁。
火车上的卫生间---经典。
同步的前提:
1,必须要有两个或者两个以上的线程。
2,必须是多个线程使用同一个锁。
必须保证同步中只能有一个线程在运行。
好处:解决了多线程的安全问题。
弊端:多个线程需要判断锁,较为消耗资源,
同步函数
在函数上加上synchronized修饰符即可。
函数需要被对象调用。那么函数都有一个所属对象引用。就是this。
所以同步函数使用的锁是this
class
Ticket
implements
Runnable {
private
static
int
tick
= 100;
public
void
run() {
while
(tick
> 1) {
[align=left] show();[/align]
[align=left] }[/align]
[align=left] }[/align]
public
synchronized
void
show() {
try
{
Thread.
sleep(10);
}
catch
(Exception e) {
[align=left] }[/align]
// synchronized (Ticket.class) {
System.
out.println(Thread.currentThread().getName()
+
".... "
+
tick--);
//tick--;
// }
[align=left] }[/align]
[align=left]}[/align]
public
class
Ts {
public
static
void
main(String[] args) {
Ticket a =
new
Ticket();// 一个实例
new
Thread(a).start();
new
Thread(a).start();
[align=left] }[/align]
[align=left]}[/align]
需求:
银行有一个金库。
有两个储户分别存300员,每次存100,存3次
class
Bank
[align=left]{[/align]
private
int
sum
;
//Object
obj = new Object();
public
synchronized
void
add(int
n)
[align=left] {[/align]
//synchronized(obj)
//{
sum
=
sum
+ n;
try{Thread.sleep(10);}
catch(Exception e){}
System.
out.println("sum="
+sum
);
//}
[align=left] }[/align]
[align=left]}[/align]
class
Cus
implements
Runnable
[align=left]{[/align]
private
Bank
b
=
new
Bank();
public
void
run()
{
for(int
x=0; x<3; x++)
[align=left] {[/align]
b.add(100);
[align=left] }[/align]
[align=left] }[/align]
[align=left]}[/align]
class
BankDemo
[align=left]{[/align]
public
static
void
main(String[] args)
[align=left] {[/align]
Cus c =
new
Cus();
Thread t1 =
new
Thread(c);
Thread t2 =
new
Thread(c);
[align=left] t1.start();[/align]
[align=left] t2.start();[/align]
}
[align=left]}[/align]
如果同步函数被静态修饰
注意:对于static的同步函数,使用的锁不是this。是 类名.class 是该类的字节码文件对象。
涉及到了单例设计模式的懒汉式
通过验证,发现不在是this。因为静态方法中也不可以定义this。
静态进内存是,内存中没有本类对象,但是一定有该类对应的字节码文件对象。
类名.class 该对象的类型是Class
静态的同步方法,使用的锁是该方法所在类的字节码文件对象。 类名.class
public
void
run()
[align=left] {[/align]
if(flag
)
[align=left] {[/align]
while(true
)
[align=left] {[/align]
synchronized(Ticket.class)
[align=left] {[/align]
if(tick
>0)
[align=left] {[/align]
try{Thread.sleep(10);}
catch(Exception e){}
System.
out.println(Thread.currentThread().getName()+
"....code : "+
tick--);
[align=left] }[/align]
[align=left] }[/align]
[align=left] }[/align]
[align=left] }[/align]
else
while(true
)
show();
[align=left] }[/align]
public
static
synchronized
void
show()
[align=left] {[/align]
if(tick
>0)
[align=left] {[/align]
try{Thread.sleep(10);}
catch(Exception e){}
System.
out.println(Thread.currentThread().getName()+
"....show.... : "+
tick--);
[align=left] }[/align]
[align=left] }[/align]
[align=left]}[/align]
死锁。
同步中嵌套同步
死锁代码一定会写。但开发时一定注意避免
class
MyLock
[align=left]{[/align]
static
Object
locka
=
new
Object();
static
Object
lockb
=
new
Object();
[align=left]}[/align]
while(true
)
[align=left]{[/align]
synchronized(MyLock.lockb)
[align=left] {[/align]
System.out.println(Thread.currentThread().getName()+
"..else lockb");
synchronized(MyLock.locka)
[align=left] {[/align]
System.out.println(Thread.currentThread().getName()+
".....else locka");
[align=left] }[/align]
[align=left] }[/align]
[align=left]}[/align]
相关文章推荐
- 黑马程序员:Java基础总结----多线程安全性&同步
- 黑马程序员:Java基础总结----多线程
- 黑马程序员:Java基础总结----子接口 List<E>及其实现类
- 黑马程序员:Java基础总结----递归的应用&File流的应用
- 黑马程序员:Java基础总结----字符字节转换流&system.in&out
- 黑马程序员:Java基础总结----GUI&网络&IO综合开发
- <黑马程序员>---java基础---多线程知识
- 黑马程序员:Java基础总结----静态代理模式&动态代理
- 黑马程序员-Java基础-多线程总结
- 黑马程序员----JAVA基础多线程&同步
- 黑马程序员 Java基础 --->多线程
- 黑马程序员:Java基础总结----字符流Reader&Writer
- 黑马程序员—7、JAVA基础&多线程
- 黑马程序员 JAVA基础<三> 多线程
- 黑马程序员:Java基础总结----接口 Collection<E>&iterator
- 黑马程序员:Java基础总结----子接口 set<E>及其实现类
- 黑马程序员:Java基础总结----对象包装类&自动装箱
- 黑马程序员 Java基础知识总结-多线程
- 黑马程序员学习log第四篇基础知识:JAVA的面向对象之多线程总结
- 黑马程序员:Java基础总结----静态代理模式&动态代理