在说线程同步之前,先简单的提一下Java线程方面的知识:Java里的多线程是通过java.lang.Thread类来实现的,每个线程都拥有自己独立的方法栈空间,Java中实现多线程主要有以下方法:
1、继承Thread类,并实现run方法。
public class myTheard extends Thread{
public void run(){
System.Out.println("线程执行");
}
}
启动方法:myTheard thread = new myTheard ();
thread .start();
2、实现Runnable接口。
public class myTheard implements Runnable{
public void run(){
System.Out.println("线程执行");
}
}
为了启动该线程,首先需要实例化一个Thread对象,并传入自己的myTread实例。
myThread mythread = new myThread ();
Thread thread = new Thread(mythread);
thread.start();
该过程实际过程为:将mythread对象传入thread后,接着便调用了mythread的run方法。
下面介绍Java线程同步相关事宜:
Java多线程同步实际上主要依赖于若干方法和关键字:包括wait、notify、notifyAll、synchronized等。
一、synchronized
在Java中每个对象都有一个内置锁,当程序运行到非静态的synchronized同步方法上时,自动获得与正在执行代码类的当前实例(this实例)有关的锁。注意:只有当程序运行到synchronized 同步方法或代码块时该对象锁才起作用,一个对象只有一个锁。所以,如果一个线程获得该锁,就没有其他线程可以获得锁,直到第一个线程释放(或返回)锁。这也意味着任何其他线程都不能进入该对象上的synchronized方法或代码块,直到该锁被释放。释放锁是指持锁线程退出了synchronized 同步方法或代码块,另外值得注意的是,synchronized只能同步方法,而不能同步变量和类。
synchronized可以有下面两种写法(非静态方法),效果相同。
public synchronized int getX() {
return x++;
}
public int getX() {
synchronized (this) {
return x++;
}
}
如果要同步静态方法,则需要一个用于整个类对象的锁,这个对象就是这个类(xxx.class)。以下两个例子效果相同。
public static synchronized int setName(String name){
xxx.name = name;
}
public static int setName(String name){
synchronized(Xxx.class){
xxx.name = name;
}
}
如果线程试图进入同步方法,而其锁已经被占用,则线程在该对象上被阻塞。实质上,线程进入该对象的的一种池中,必须在那里等待,直到其锁被释放,该线程再次变为可运行或运行位置。
二、wait
wait()允许我们将线程置入“睡眠”状态",也就是说,wait也是让当前线程阻塞的,这一点和sleep或者suspend是相同的。而wait和sleep、suspend的区别在于当执行wait方法后,如果当前代码块持有对象锁,那么此时该线程会暂时让出该锁,让其他的线程先执行,等到其他线程执行完后(当其他线程调用notify或notifyAll后)才继续执行该代码块。这意味着可在执行wait期间调用线程对象中的其他同步方法,而这对于sleep和suspend是不可能的。 但是注意我前面说的,只是暂时放弃对象锁,暂时给其它线程使用,wait所在的线程还是要把这个对象锁收回来的,wait嘛,就是wait别人用完了还给我呗。那怎么把对象锁收回来呢?
第一种方法,限定借出去的时间。在wait()中设置参数,比如wait(1000),以毫秒为单位,就表明只借出去1秒中,一秒钟之后,自动收回。
第二种方法,让借出去的主动通知,对方用完了,要还给我了,这时,我马上就收回来,那么别人怎么通知我呢?当然是notify()了,只有在一个notify()或notifyAll()发生变化的时候,线程才会被唤醒。 因此,我们可将一个wait()和notify()置入任何同步方法或同步块内部,无论在那个类里是否准备进行涉及线程的处理。而且实际上,我们也只能在同步方法或者同步块里面调用wait()和notify()。
三、notify、notifyAll
这两个方法已经在wait中阐明意思了,这里就不再罗嗦了
好了,关于Java线程同步暂时只了解这些,将来有新发现再补充吧。