黑马程序员:Java基础总结
多线程安全性&同步
Java对于多线程的安全问题提供了专业的解决方式。
同步代码块
synchronized(对象)
{
需要被同步的代码
}
对象如同锁。持有锁的线程可以在同步中执行。
没有持有锁的线程即使获取cpu的执行权,也进不去,因为没有获取锁。
火车上的卫生间---经典。
同步的前提:
1,必须要有两个或者两个以上的线程。
2,必须是多个线程使用同一个锁。
必须保证同步中只能有一个线程在运行。
好处:解决了多线程的安全问题。
弊端:多个线程需要判断锁,较为消耗资源,
同步函数
在函数上加上synchronized修饰符即可。
函数需要被对象调用。那么函数都有一个所属对象引用。就是this。
所以同步函数使用的锁是this
class
Ticket
implements
Runnable {
private
static
int
tick
= 100;
public
void
run() {
while
(
tick
> 1) {
show();
}
}
public
synchronized
void
show() {
try
{
Thread. sleep(10);
}
catch
(Exception e) {
}
// synchronized (Ticket.class) {
System.
out
.println(Thread.currentThread().getName() +
".... "
+
tick
--);
//tick--;
// }
}
}
public
class
Ts {
public
static
void
main(String[] args) {
Ticket a =
new
Ticket();
// 一个实例
new
Thread(a).start();
new
Thread(a).start();
}
}
需求:
银行有一个金库。
有两个储户分别存300员,每次存100,存3次
银行有一个金库。
有两个储户分别存300员,每次存100,存3次
class
Bank
{
private
int
sum
;
//Object obj = new Object();
public
synchronized
void
add(
int
n)
{
//synchronized(obj)
//{
sum
=
sum
+ n;
try
{Thread.sleep(10);}
catch
(Exception e){}
System.
out
.println(
"sum="
+
sum
);
//}
}
}
class
Cus
implements
Runnable
{
private
Bank
b
=
new
Bank();
public
void
run()
{
for
(
int
x=0; x<3; x++)
{
b
.add(100);
}
}
}
class
BankDemo
{
public
static
void
main(String[] args)
{
Cus c =
new
Cus();
Thread t1 =
new
Thread(c);
Thread t2 =
new
Thread(c);
t1.start();
t2.start();
}
}
如果同步函数被静态修饰
通过验证,发现不在是this。因为静态方法中也不可以定义this。
静态进内存是,内存中没有本类对象,但是一定有该类对应的字节码文件对象。
类名.class 该对象的类型是Class
静态的同步方法,使用的锁是该方法所在类的字节码文件对象。 类名.class
注意:对于static的同步函数,使用的锁不是this。是 类名.class 是该类的字节码文件对象。
涉及到了单例设计模式的懒汉式
涉及到了单例设计模式的懒汉式
通过验证,发现不在是this。因为静态方法中也不可以定义this。
静态进内存是,内存中没有本类对象,但是一定有该类对应的字节码文件对象。
类名.class 该对象的类型是Class
静态的同步方法,使用的锁是该方法所在类的字节码文件对象。 类名.class
public
void
run()
{
if
(
flag
)
{
while
(
true
)
{
synchronized
(Ticket.
class
)
{
if
(
tick
>0)
{
try
{Thread.sleep(10);}
catch
(Exception e){}
System.
out
.println(Thread.currentThread().getName()+
"....code : "
+
tick
--);
}
}
}
}
else
while
(
true
)
show();
}
public
static
synchronized
void
show()
{
if
(
tick
>0)
{
try
{Thread.sleep(10);}
catch
(Exception e){}
System.
out
.println(Thread.currentThread().getName()+
"....show.... : "
+
tick
--);
}
}
}
死锁。
同步中嵌套同步
同步中嵌套同步
死锁代码一定会写。但开发时一定注意避免
class
MyLock
{
static
Object
locka
=
new
Object();
static
Object
lockb
=
new
Object();
}
while
(
true
)
{
synchronized
(MyLock.lockb)
{
System.out.println(Thread.currentThread().getName()+
"..else lockb"
);
synchronized
(MyLock.locka)
{
System.out.println(Thread.currentThread().getName()+
".....else locka"
);
}
}
}