所谓的同步指的并不是所有的线程一起进入到方法中执行,而是按照顺寻一个一个的进来
Synchronized 处理同步问题
使用Synchronized关键字处理有两种模式:同步代码块,同步方法
一、同步代码块:
如果要使用同步代码块必须设置一个要锁定的对象,所以一般可以锁定当前对象。
并且synchronized 同步的代码块,在同一时刻只允许一个线程进入代码块处理
这种方式是在方法中拦截的,也就是说进入到方法中的线程依然会有很多个。
class MyThread implements Runnable{
private int ticket=10;
public void run() {
for(int i=0;i<10;i++) {
//synchronized 在同一时刻只允许一个线程进入代码块处理
synchronized (this) {
try {
Thread.sleep(1000);
System.out.println("当前进程名"+Thread.currentThread().getName()+
"、还剩票数:"+ticket--);
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
}
}
public class Test2 {
public static void main(String[] args) {
MyThread myThread=new MyThread();
Thread t1=new Thread(myThread,"黄牛A");
Thread t2=new Thread(myThread,"黄牛B");
t1.start();
t2.start();
}
}
二、同步方法
进入到方法中的线程只有一个。
class MyThread implements Runnable{
private int ticket=10;
public void run() {
for(int i=0;i<10;i++) {
this.sale();
}
}
//进入到方法中的线程只有一个
public synchronized void sale() {
if(this.ticket>0) {
try {
Thread.sleep(100);
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
System.out.println("当前线程为"+Thread.currentThread().getName()
+"剩余票数:"+this.ticket--);
}
}
}
public class Test2 {
public static void main(String[] args) {
MyThread myThread=new MyThread();
Thread t1=new Thread(myThread,"黄牛A");
Thread t2=new Thread(myThread,"黄牛B");
t1.start();
t2.start();
}
}
对象锁:
锁住同一个对象
class Sync{
public void test() {
synchronized(this) {
System.out.println("test方法开始,当前线程为:"+Thread.currentThread().getName());
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
System.out.println("test方法结束,当前线程为:"+Thread.currentThread().getName());
}
}
}
class MyThread implements Runnable{
private Sync sync;
public MyThread(Sync sync) {
super();
this.sync = sync;
}
public void run() {
this.sync.test();
}
}
public class Test2 {
public static void main(String[] args) {
Sync sync=new Sync();
MyThread myThread=new MyThread(sync);
for(int i=0;i<3;i++) {
Thread thread=new Thread(myThread);
thread.start();
}
}
}
全局锁:
使用synchronized锁住这个类对应的Class对象
下面代码使用synchronized(Sync.class)实现了全局锁的效果,因此要想锁住的是代码段,锁住多个对象的同一方法,使用这种全局锁,锁住的是类而不是this
static synchronized 方法,staic方法可以直接类名加方法名调用,方法中无法使用this,所以它锁的不是this,而是类的class对象,,所以statci synchronized 方法也相当于全局锁,相当于锁住了代码段。
class Sync{
public void test() {
synchronized(Sync.class) {
System.out.println("test方法开始,当前线程为:"+Thread.currentThread().getName());
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
System.out.println("test方法结束,当前线程为:"+Thread.currentThread().getName());
}
}
}
class MyThread implements Runnable{
public void run() {
Sync sync=new Sync();
sync.test();
}
}
public class Test2 {
public static void main(String[] args) {
for(int i=0;i<3;i++) {
MyThread myThread=new MyThread();
Thread thread=new Thread(myThread);
thread.start();
}
}
}
JDK1.5提供的Lock锁
class MyThread implements Runnable{
private int ticket=10;
private Lock ticketLock=new ReentrantLock();
public void run() {
for(int i=0;i<10;i++) {
ticketLock.lock();
if(this.ticket>0) {
try {
try {
Thread.sleep(100);
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
System.out.println("当前进程为:"+Thread.currentThread().getName()+
"剩余票数:"+this.ticket--);
} finally {
ticketLock.unlock();
}
}
}
}
}
public class Test2 {
public static void main(String[] args) {
MyThread myThread=new MyThread();
Thread thread=new Thread(myThread,"黄牛A");
Thread thread2=new Thread(myThread,"黄牛B");
Thread thread3=new Thread(myThread,"黄牛C");
thread.start();
thread2.start();
thread3.start();
}
}