本文主要是将synchronized关键字用法作为例子来去解释Java中的对象锁和类锁。特别的是希望能帮大家理清一些概念。
一、synchronized关键字
synchronized关键字有如下两种用法:
1、 在需要同步的方法的方法签名中加入synchronized关键字。
synchronized public void getValue() {
System.out.println("getValue method thread name="
+ Thread.currentThread().getName() + " username=" + username
+ " password=" + password);
}12345
上面的代码修饰的synchronized是非静态方法,如果修饰的是静态方法(static)含义是完全不一样的。具体不一样在哪里,后面会详细说清楚。
synchronized static public void getValue() {
System.out.println("getValue method thread name="
+ Thread.currentThread().getName() + " username=" + username
+ " password=" + password);
}12345
2、使用synchronized块对需要进行同步的代码段进行同步。
public void serviceMethod() {
try {
synchronized (this) {
System.out.println("begin time=" + System.currentTimeMillis());
Thread.sleep(2000);
System.out.println("end end=" + System.currentTimeMillis());
}
} catch (InterruptedException e) {
e.printStackTrace();
}
}
上面的代码块是synchronized (this)
用法,还有synchronized (非this对象)
以及synchronized (类.class)
这两种用法,这些使用方式的含义也是有根本的区别的。我们先带着这些问题继续往下看。
4、synchronized (非this对象)
我们先看看代码实例(Run.java)
public class Run {
public static void main(String[] args) {
Service service = new Service("xiaobaoge");
ThreadA a = new ThreadA(service);
a.setName("A");
a.start();
ThreadB b = new ThreadB(service);
b.setName("B");
b.start();
}
}
class Service {
String anyString = new String();
public Service(String anyString){
this.anyString = anyString;
}
public void setUsernamePassword(String username, String password) {
try {
synchronized (anyString) {
System.out.println("线程名称为:" + Thread.currentThread().getName()
+ "在" + System.currentTimeMillis() + "进入同步块");
Thread.sleep(3000);
System.out.println("线程名称为:" + Thread.currentThread().getName()
+ "在" + System.currentTimeMillis() + "离开同步块");
}
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
class ThreadA extends Thread {
private Service service;
public ThreadA(Service service) {
super();
this.service = service;
}
@Override
public void run() {
service.setUsernamePassword("a", "aa");
}
}
class ThreadB extends Thread {
private Service service;
public ThreadB(Service service) {
super();
this.service = service;
}
@Override
public void run() {
service.setUsernamePassword("b", "bb");
}
}
不难看出,这里线程争夺的是anyString的对象锁,两个线程有竞争同一对象锁的关系,出现同步。
这里的 anyString
是在jvm的字符串常量池中,地址是一样的。所以能保证多个实例
对象也能在一个锁中。使用synchronized(任意自定义对象)进行同步操作,对象监视器必须是同一个对象。不过不是同一个,运行就是异步执行了。这里anyString是同一个对象
同步synchronized(*.class)
代码块的作用其实和synchronized static
方法作用一样。Class锁对类的所有对象实例起作用。
synchronize修饰的方法和synchronize(this)
都是锁住自己本身的对象
,synchronized(*.class)是锁住加载类对象
,synchronized(object)是锁住object对象
吧
转自:https://blog.csdn.net/u013142781/article/details/51697672