线程同步
为什么需要“线程同步”
线程间共享代码和数据可以节省系统开销,提高程序运行效率,但同时也导致了数据的“访问冲突”问题,如何实现线程间的有机交互、并确保共享资源在某些关键时段只能被一个线程访问,即所谓的“线程同步”(Synchronization)就变得至关重要。
临界资源
多个线程间共享的数据称为临界资源(Critical Resource),由于是线程调度器负责线程的调度,程序员无法精确控制多线程的交替顺序。因此,多线程对临界资源的访问有时会导致数据的不一致行。
同步的两种表现形式:
1.同步代码块
synchronized(对象){
需要同步的代码
}
2.同步函数:使用的锁是this
public synchronized void show(){
}
同步的作用:避免线程的安全隐患
例子
class Tickets{
publicint tickets;
publicTickets(){
tickets=10;
}
publicsynchronized void action(String name){
System.out.println(name+"买了"+tickets+"票");
tickets--;
}
}
class TicketsThread extends Thread{
Ticketst;
Stringname;
publicTicketsThread(Tickets t,String name){
this.t=t;
this.name=name;
start();
}
publicvoid run(){
for(inti=0;i<5;i++){
t.action(name);
try{
Thread.sleep(20);
}catch (InterruptedException e) {
//TODO Auto-generated catch block
e.printStackTrace();
}
}
}
}
public class TestMulThread {
/**
* @param args
*/
publicstatic void main(String[] args) {
Ticketst=new Tickets();
TicketsThreadt1=new TicketsThread(t,"小张");
TicketsThreadt2=new TicketsThread(t,"小王");
}
}
单例式
懒汉式
class Single{
private static Single s=null;
private Single(){}
public static Single getInstance(){
if(s==null)
synchronized(Singel。class){
if(s==null)
s=new Single();
}
return s;
}
class Single{
private static Single s=null;
private Single(){}
public static synchronized Single getInstance(){
if(s==null)
s=new Single();
return s;
}
Single。getInstance();
饿汉式
class Single{
private static Single s=new Single();
private Single(){}
public static Single getInstance(){
return s;
}
死锁
两个线程A、B用到同一个对象s(s为共享资源),且线程A在执行中要用到B运行后所创造的条件。在这种前提下A先开始运行,进入同步块后,对象s被锁定,接着线程A因等待B运行结束而进入阻塞状态,于是B开始运行,但因无法访问对象s,线程B也进入阻塞状态,等待s被线程A解锁。最终的结果:两个线程互相等待,都无法运行。
例子:
public class DeadLock {
/**
* @param args
*/
publicstatic void main(String[] args) {
Demo6d1=new Demo6(true);
Demo6d2=new Demo6(false);
Threadt1=new Thread(d1);
Threadt2=new Thread(d2);
t1.start();
t2.start();
}
}
class MyLock{
staticMyLock lock1=new MyLock();
staticMyLock lock2=new MyLock();
}
class Demo6 implements Runnable{
//Stringstr1=new String("aaa");
//Stringstr2=new String("bbb");
privateboolean flag;
publicDemo6(boolean flag){
this.flag=flag;
}
@Override
publicvoid run() {
if(flag){
synchronized(MyLock.lock1){
System.out.println(Thread.currentThread().getName()+"...if...str1");
synchronized(MyLock.lock2){
System.out.println(Thread.currentThread().getName()+"...if...str2");
}
}
}else{
synchronized(MyLock.lock2){
System.out.println(Thread.currentThread().getName()+"...else...str2");
synchronized(MyLock.lock1){
System.out.println(Thread.currentThread().getName()+"...else...str1");
}
}
}
}
}