锁对象是什么:
在初次接触到线程锁对象这个问题时,我并没有在意锁对象这个问题,只知道被Synchroized修饰的代码块只能同时被一个线程访问。这样理解虽然简单,却也很片面,只是设想到了一个线程占用一个锁的情况,却没有考虑到一个线程其实可以拥有多把锁,并且占用它。
什么是锁对象?
锁对象其实就是锁,锁对象可以是当前Runnable实现类的对象,也可以是Runnable实现类的类,即.class。
1、synchronized修饰方法时 锁对象时当前的Runnable实现类的对象
2、synchronized修饰静态方法 锁对象是Runnable实现类的类,即.class
class MyThread implements Runnable {}//自定义了Runnable实现类
public synchronized void setStr() {} //synchronized修饰方法时 锁对象时当前的Runnable实现类的对象
public synchronized static void uppSet3(){}//synchronized修饰静态方法 锁对象是Runnable实现类的类,即.class
//在需要使用到该类对象的类里面,创建锁对象
MyThread run1 =new MyThread();
此时我们创建线程时,如果传入相同的锁对象,那么对于被synchronized修饰的方法或者代码块就被同一把锁对象run1给锁住了,这样就能实现线程安全!
//创建线程对象
Thread t1 =new Thread(run1,"t1");
Thread t2 =new Thread(run1,"t2");
锁对象一定要是实现Runnable实现类的对象吗
锁对象也不一定要是实现Runnable实现类的对象,我们可以随便定义一个类,为其创建对象,并将该对象作为锁对象,尽管这个类实际上并没有任何的业务逻辑上的实现。
public static Object lock =new Object();//随便定义了一个对象
‘’‘’在需要的代码块中将其作为锁对象‘’‘’‘’
@Override
public void run() {
//声明同步代码块,其中 的代码同时只能被一个线程访问
synchronized (Acount2.lock){
if (Acount2.balance>monry){
try{
TimeUnit.SECONDS.sleep(1);
}catch (InterruptedException E){
System.out.println(E.getMessage());
}
//更改余额
Acount2.balance = Acount2.balance-monry;
System.out.println(name+"取钱成功,当前余额"+Acount2.balance);
}
else {
System.out.println(name+"取钱失败,当前余额"+Acount2.balance);
}
}
}
总结
每个线程可以拥有多个锁对象(锁),当线程要访问被锁管理的代码块时,都先要获得这把锁的使用权(看看当前这把锁是否被其他线程所占用)。如果该线程所需要的锁被其他线程正占用着,该线程只能等待,等到其他线程释放之后才能使用,如果其他线程不释放,而这个线程又一直等着要用,那么就会造成死锁问题,关于死锁问题,将在下一篇的"线程死锁问题案例分析及解决方案"中详细描述。