1.同步问题
在多线程下每一个线程对象轮番抢占资源,这个造成了很大的问题。比如当多个线程买票出现了负数,这种问题被称为不同步操作,不同步的好处是多个线程并发执行,这样处理速度快,synchronized是Java中的关键字,它主要解决的是线程同步问题。
同步处理:所有线程不是同时获取资源,而是按顺序一个一个来。那这就需要一把锁,锁住对应的资源,但是不同锁锁的是不同的资源。内建锁:(synchronized):JDK1.0作为关键提供的手段。
2.同步代码块:
使用synchronized作用于方法里,但是进入到方法中的线程依然有多个,是在方法里进行拦截,同一时刻只能有一个线程进入代码块,方法内仍然是多线程。
总结:
synchronized(this/ 当前类.class / 任意Object的子类对象) {同步代码段}
总结:
- synchronized(this){}:锁类的实例对象(当前对象)
- synchronized(类名称.class){}:锁类对象(class对象)
- synchronized(任意类对象){}:任意Object的子类对象
3.同步方法
在方法上添加synchronized关键字,表示此方法只有一个线程能进入, 使用synchronized作用于方法头,同一时刻只有一个线程进入此方法
public synchroized void sale()
public static synchroized void sale()
总结:
- synchronized+普通方法:锁当前对象
- synchronized+静态方法:锁当前类的对象(class对象)
所有代码示例:
package JavaSe.mult;
//class Buy implements Runnable{
// private int ticket=100;
// @Override
// public void run() {
// for(int i=0;i<100;i++){
// synchronized (this){//表示为程序逻辑上锁,在一个时刻只可以有一个线程进入代码块
// if(this.ticket>0){
// try {
// Thread.sleep(20);
// } catch (InterruptedException e) {
// e.printStackTrace( );
// }
// System.out.println(Thread.currentThread().getName()+"还有"+this.ticket--+"票" );
// }
// }
// }
// }
//}
//class Buy implements Runnable{
// private int ticket=100;
// @Override
// public void run() {
// for(int i=0;i<100;i++){
// this.sale();
// }
// }
// public synchronized void sale(){//任意时刻只有一个线程进入此方法,隐式锁对象
// if(this.ticket>0){
// try {
// Thread.sleep(20);
// } catch (InterruptedException e) {
// e.printStackTrace( );
// }
// System.out.println( Thread.currentThread().getName()+"还有"+this.ticket--+"票");
// }
// }
//}
//
//class Buy extends Thread{
// @Override
// public void run() {
// Sync sync=new Sync();
// sync.test();//锁的是多对象,任意时刻只有一个线程(同一个对象)能进入此方法
// }
//}
//class Sync{
// public synchronized void test(){
// System.out.println("test方法开始,当前线程为"+Thread.currentThread().getName() );
// try {
// Thread.sleep(30);
// } catch (InterruptedException e) {
// e.printStackTrace( );
// }
// System.out.println("test方法结束,当前线程为"+Thread.currentThread().getName() );
// }
//}
class Buy implements Runnable{
//Sync sync=new Sync();也是一把锁
@Override
public void run() {
Sync sync=new Sync();//三把锁
sync.test();//锁的是多对象,任意时刻只有一个线程(同一个对象)能进入此方法
}
}
class Sync{
//public static synchronized void test(){//与对象无关了,synchronized修饰的是静态方法,
//或者是synchronized(类名称,class) 则锁的是当前类的反射对象(class对象)(全局唯一)
public void test(){
synchronized (Sync.class){
System.out.println("test方法开始,当前线程为"+Thread.currentThread().getName() );
try {
Thread.sleep(300);
} catch (InterruptedException e) {
e.printStackTrace( );
}
System.out.println("test方法结束,当前线程为"+Thread.currentThread().getName() );
}
}
}
public class TestSynchronized {
public static void main(String[] args) {
// Buy buy=new Buy();
// Thread thread1=new Thread(buy,"A");
// Thread thread2=new Thread(buy,"B");
// Thread thread3=new Thread(buy,"c");
//
// thread1.start();
// thread2.start();
// thread3.start();
Buy buy=new Buy();
for(int i=0;i<3;i++){
Thread thread=new Thread(buy);
thread.start();
}
}
}
同步虽然可以保证数据的完整性(线程安全操作),但是其执行的速度会很慢
4.全局锁:
实现全局锁的方式:
a.synchronized(类.class对象)
b.使用static synchronized方法
全局锁,与实例对象无关,锁的类(class)对象!!