先来看一段代码:

class MyThread implements Runnable{
	private int count = 10;
	@Override
	public void run() {
		while(count > 0) {
			System.out.println(Thread.currentThread().getName() + "开始执行");
			System.out.println("count还剩" + --count);
			System.out.println(Thread.currentThread().getName() + "执行结束");
			System.out.println();
		}
	}	
}

public class Test{
	public static void main(String[] args) {
		MyThread myThread = new MyThread();
		new Thread(myThread).start();
		new Thread(myThread).start();
		new Thread(myThread).start();
	}
}
登录后复制

运行结果如下:

Thread-0开始执行
Thread-2开始执行
Thread-1开始执行
count还剩8
count还剩9
Thread-2执行结束
count还剩7
Thread-1执行结束

Thread-1开始执行

Thread-0执行结束

Thread-0开始执行
count还剩5
Thread-0执行结束

Thread-2开始执行
count还剩4
Thread-2执行结束

Thread-2开始执行
count还剩3
count还剩6
Thread-2执行结束

Thread-2开始执行
Thread-0开始执行
count还剩2
Thread-2执行结束

Thread-2开始执行
count还剩0
Thread-2执行结束

Thread-1执行结束

count还剩1
Thread-0执行结束
登录后复制

很显然这并不是我们想要的结果,我们想要的结果是:一个独自完整地按顺序跑完自己的run()方法,然而上面的结果是乱序的:上一个线程还没有跑完自己的任务,第二个线程就进来了。那么如何来解决这个问题呢?

首先我们来分析一下,三个线程同时拿到我们自己创建的对象myThread,然后启动这三个线程,这三个线程会同时进入这个run()方法进行执行。如果我们想要每一个线程进入后完整的跑完自己的任务,这时候就需要把这个myThread对象锁起来,不让其他线程拿到,这样就能实现。就比如说,有一个房间,你进入之后,不想要其他人再进来,你就得把门锁住一个道理。

在Java里面为我们提供了一个叫做“synchronized”的锁子。那么它应该怎样来使用呢?

“synchronized”的两种模式:同步方法、同步代码块。

一、对象锁:

1、同步代码块:在代码块前面加上synchronized(要锁的对象)。

class MyThread implements Runnable{
	private int count = 10;
	@Override
	public void run() {
		synchronized (this) {
			while(count > 0) {
				System.out.println(Thread.currentThread().getName() + "开始执行");
				System.out.println("count还剩" + --count);
				System.out.println(Thread.currentThread().getName() + "执行结束");
				System.out.println();
			}
		}	
	}	
}

public class Test{
	public static void main(String[] args) {
		MyThread myThread = new MyThread();
		new Thread(myThread).start();
		new Thread(myThread).start();
		new Thread(myThread).start();
	}
}
登录后复制

2、同步方法:在方法的返回值前面加上synchronized关键字。

class MyThread implements Runnable{
	private int count = 10;
	@Override
	public void run() {
		while(count > 0) {
			count--;
			fun();
		}
	}
	public synchronized void fun() {
		System.out.println(Thread.currentThread().getName() + "开始执行");
		System.out.println("count还剩" + count);
		System.out.println(Thread.currentThread().getName() + "执行结束");
		System.out.println();
	}
}

public class Test{
	public static void main(String[] args) {
		MyThread myThread = new MyThread();
		new Thread(myThread).start();
		new Thread(myThread).start();
		new Thread(myThread).start();
	}
}
登录后复制

二、全局锁:

在上面,我们锁住的都是myThread对象,如果要锁住多个对象的同一个方法又该怎么办呢?

这里与对象锁也有两种方法:同步方法和同步代码块。

1、同步代码块前的括号里写成想要锁住的方法的类.class

class MyThread implements Runnable{
	private static int count = 10;
	@Override
	public void run() {
		synchronized (MyThread.class) {
			while(count > 0) {
				count--;
				fun();
			}
		}	
	}
	public void fun() {
		System.out.println(Thread.currentThread().getName() + "开始执行");
		System.out.println("count还剩" + count);
		System.out.println(Thread.currentThread().getName() + "执行结束");
		System.out.println();
	}
}

public class Test{
	public static void main(String[] args) {
		MyThread myThread = new MyThread();
		new Thread(myThread).start();
		new Thread(myThread).start();
		new Thread(myThread).start();
	}
}
登录后复制

2、在前面所说同步方法的基础上,加上static关键字,就可以实现全局锁。

class MyThread implements Runnable{
	private static int count = 10;
	@Override
	public void run() {
		while(count > 0) {
			fun();
		}
	}
	public synchronized static void fun() {
		System.out.println(Thread.currentThread().getName() + "开始执行");
		System.out.println("count还剩" + count);
		System.out.println(Thread.currentThread().getName() + "执行结束");
		System.out.println();
		count--;
	}
}

public class Test{
	public static void main(String[] args) {
		MyThread myThread = new MyThread();
		new Thread(myThread).start();
		new Thread(myThread).start();
		new Thread(myThread).start();
	}
}
登录后复制

相关文章:

Java同步锁(synchronized)的示例代码分享

详解Java中synchronized关键字的死锁和内存占用问题

相关视频:

全面解析Java注解

以上就是Java:详细讲解对象锁“synchronized”与全局锁的详细内容,更多请关注Work网其它相关文章!

09-18 18:24