由于代码过于分散,此篇博客就没有把代码贴出来,作为新年的第一篇博客,工作过于忙碌,没有时间看书和总结了,希望在新的2016年,能够继续深入了解Java。加油,可能是个最差的程序员。这是一篇未完结的博客,下次再补上。
1、方法内部的变量为线程安全
“非线程安全”问题存在于“实例变量”中,如果是方法内部的私有变量,则不存在“非线程安全”问题。这是方法内部的变量是私有的特性造成的
2、实例变量是非线程安全的
如果多个线程共同访问一个对象中得实例变量,则有可能造成“非线程安全”问题。
3、多个对象多个锁
锁的概念是针对对象的,每一个对象都会有锁(lock)关键字synchronized取得的锁都是对象锁,而不是把一段方法或者代码当做锁,哪个线程先执行带synchronized关键字的方法,哪个线程就持有该方法所属对象的锁(lock),那么其他线程都必须处在等待状态。
多个线程访问多个对象,则JVM会创建多个锁。
4、synchronized方法与锁对象
调用关键字synchronized声明的方法一定是排队运行的,只有共享资源的读写访问才需要同步,如果不是共享资源,那么根本没有同步的必要,多个方法被synchronized关键字修饰,多个线程调用这些方法也必须排队执行。
A线程先持有object对象的lock锁,B线程可以以异步的方式调用object对象中得非synchronized类型的方法
A线程先持有object对象的lock锁,B线程如果在这时需要调用object对象中得synchronized类型的方法则需要等待,也就是同步
5、synchronized 锁重入
关键字synchronized拥有锁重入功能,也就是在使用synchronized时,当一个线程得到一个对象锁后,再次请求改对象锁时是可以再次得到该对象的锁的,简而言之,synchronized 方法/代码块内部调用奔雷的其他的synchronized方法/代码块,是永远可以得到锁的。此设计的基础是避免死锁,即有synchronized方法MethodA,在MethodA中调用了synchronized方法MethodB,是可以直接获取该锁的。而且在继承关系中,子类完全可以通过“可重入锁”调用父类的同步方法
6、出现异常,锁自动释放
7、同步不具备继承性
父类有synchronized方法SuperMethod(),子类重写父类该方法,未申明为synchronized的方法,子类的该方法并不具有synchronized属性,因为同步不具备继承性
8、synchronized方法的弊端
当线程持有某对象的锁的情况下,该方法需要做耗时操作的时候,别的线程需要长期等待,造成效率地下的问题。此处可以引入synchronized的代码块,通常可将赋值操作用synchronized(this)同步该赋值代码块,而耗时操作中保持异步执行,这样子的做法即保证了代码的异步高效,同时能够确保赋值操作的同步性,不会造成脏读。
9、synchronized代码块之间的同步性
在使用synchronized(this)代码块的时候需要注意的是:当一个线程访问object的synchronized(this)同步代码块时,其他线程对同一个object中所有其他的synchron(this)同步代码快的方法将被阻塞。
10、synchronized(this)代码块是锁定当前对象的
和synchronized方法一样,synchronized(this)代码块也是锁定当前对象的,也就是说持有的锁为当前对象的锁,线程A在调用ObjectA的sychronized(this)代码块时,线程B是无法调用ObjectA的synchronized方法的
11、将任意对象作为对象监视器
synchronized(非this对象)格式的作用只有一个种:synchronized(非this对象)同步代码块。在多个线程持有”线程监视器”为同一个对象的前提下,同一时间只有一个线程可以执行synchronized(非this对象)同步代码块中得代码,当持有”对象监视器”为同一个对象的前提下,同一时间只有一个线程可以执行synchronized(非this对象)同步代码块中得代码
synchronized(非this对象)的优点:如果一个类中有很多synchronized方法,这时虽然能够实现方法同步,但会收到阻塞,所以会影响运行效率,但如果使用synchronized(非this对象),此时该代码块与synchronized方法是异步的,不与其他锁this同步方法争抢this锁,可以大大提高运行效率。显然,synchronized中的对象必须是同一个对象,否则他们持有的锁就不是同一个锁了,所以就会造成异步。
12、静态同步synchronized方法与synchronized(class)代码块
关键字synchronized还可以应用在static静态方法中,如果这样子写,那是对当前的.java文件对应的Class类进行持锁,给Class类加锁。而在非static方法中是对对象加锁。同步synchronized(class)代码块的作用其实和synchronized static方法的作用是一样的。
13、不要使用synchronized(String)此类锁,。
因为在JVM中有一个String池的概念,容易导致持有相同对象的锁,以至于造成死锁。Java线程死锁是一个经典的多线程问题,因为不同的线程都在等候根本不可能被释放的锁,从而导致所有的任务都无法继续完成,在多线程技术中,“死锁”是必须避免的,因为这会造成线程的“假死”。早成死锁的一个例子
public class DealThread implements Runnale
{
public String username;
public Object lock1 = new Object();
public Object lock2 = new Object();
public void setFlag(String username)
{
this.username = username;
}
@Override
public void run()
{
if(“a”.equals(username))
{//持有lock1等待lock2
synchronized(lock1)
{
try
{
System.out.print(“username = “ + username);
Thread.sleep(3000);
}
catch(InterruptException e)
{
e.printStackTrace();
}
synchronized(lock2)
{
System.out.print(“按lock1 -> lock2 代码顺序执行“);
}
}
}
if(“b”.equals(username))
{//持有lock2等待lock1
synchronized(lock2)
{
try
{
System.out.print(“username = “ + username);
Thread.sleep(3000);
}
catch(InterruptException e)
{
e.printStackTrace();
}
synchronized(lock1)
{
System.out.print(“按lock2 -> lock1 代码顺序执行“);
}
}
}
}
}
死锁是程序设计的bug,在设计程序的时候就要避免双方相互持有对方的锁的情况。只要互相等待对方释放的锁就有可能造成死锁。
13、锁对象的改变
在将任何数据类型作为同步锁时,需要注意的是,是否有多个线程同时持有锁对象,如果同时持有相同的锁对象,则这些线程之间就是同步的,如果分别获得锁对象,这些线程之间就是异步的。持有锁的过程中,可以改变锁对象,改变锁对象的时候,原来那个锁被释放。只要锁对象不变,即使对象的属性改变,运行的结果还是同步的。