java的加锁机制是synchronized。加锁有分三种情况。
1,代码块加锁。2,方法加锁。3,静态方法加锁。很明显可以知道这三种加锁的对象是不一样的。
一,代码块加锁
代码块加锁是作用于整个代码块,锁的对象是可以任意的对象。只要这个任意的对象是同一个对象就可以保证线程的安全。
public class SellTicket implements Runnable {
// 定义100张票
private static int tickets = 100;
// 定义同一把锁
private Object obj = new Object();
private Demo d = new Demo();
@Override
public void run() {
while (true) {
synchronized (obj) { //这里的锁对象可以obj 也可以是d。因为代码的锁对象是任意的对象
if (tickets > 0) {
try {
Thread.sleep(100);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println(Thread.currentThread().getName()
+ "正在出售第" + (tickets--) + "张票 ");
}
}
}
}
二,方法锁
方法锁的对象是做作用于整个方法,锁的对象是当前对象。不能是任意对象。方法锁不需要加锁的对象,锁的对象默认的就是当前的对象。所以加锁的机制的时候要保证多个线程用的是同一个对象。
private synchronized void sellTicket() {
if (tickets > 0) {
try {
Thread.sleep(100);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println(Thread.currentThread().getName()
+ "正在出售第" + (tickets--) + "张票 ");
}
}
三,静态方法的锁
我们知道静态方法是随着类的,不是对象。所以静态方法的锁是类的对象。静态方法的锁对象也是不需要指定,自己默认的
private static synchronized void sellTicket() {
if (tickets > 0) {
try {
Thread.sleep(100);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println(Thread.currentThread().getName()
+ "正在出售第" + (tickets--) + "张票 ");
}
}
说完了上面各自的所得对象,那么稍微总结一下。
锁代码块的效率是最高的,而且是作用于方法。一般推荐使用的是锁代码块。
需要注意的是,线程实现的方法有继承Thread和现实Runnable接口两种方式比较多。由于这种实现的方式有点差异。实际上用于锁是不一样。