Java语言的关键字,当它用来修饰一个方法或者一个代码块的时候,能够保证在同一时刻最多只有一个线程执行该段代码。
成都创新互联公司-专业网站定制、快速模板网站建设、高性价比顺昌网站开发、企业建站全套包干低至880元,成熟完善的模板库,直接使用。一站式顺昌网站制作公司更省心,省钱,快速模板网站建设找我们,业务覆盖顺昌地区。费用合理售后完善,十多年实体公司更值得信赖。
一、当两个并发线程访问同一个对象object中的这个synchronized(this)同步代码块时,一个时间内只能有一个线程得到执行。另一个线程必须等待当前线程执行完这个代码块以后才能执行该代码块。
二、然而,当一个线程访问object的一个synchronized(this)同步代码块时,另一个线程仍然可以访问该object中的非synchronized(this)同步代码块。
三、尤其关键的是,当一个线程访问object的一个synchronized(this)同步代码块时,其他线程对object中所有其它synchronized(this)同步代码块的访问将被阻塞。
四、第三个例子同样适用其它同步代码块。也就是说,当一个线程访问object的一个synchronized(this)同步代码块时,它就获得了这个object的对象锁。结果,其它线程对该object对象所有同步代码部分的访问都被暂时阻塞。
五、以上规则对其它对象锁同样适用.
线程同步主要有以下种方法(示例中是实现计数的功能):
1、同步方法,即使用synchronized关键字修饰方法,例如:
public synchronized void add(int c){...}
2、同步代码块,即有synchronized关键字修饰的语句块,例如:
public void addAndGet(int c){
synchronized(this){
count += c;
}
}
3、使用特殊域变量(volatile)实现线程同步,该方法不能保证绝对的同步。
例如:private volatile int count = 0;
4、使用锁实现线程同步,例如:
private Lock lock = new ReentrantLock();
public void add(int c) {
lock.lock();//上锁
try{
count += c;
}finally{
lock.unlock();//解锁
}
}
5、使用原子变量实现线程同步,在java的util.concurrent.atomic包中提供了创建了原子类型变量的工具类,例如:
private AtomicInteger count= new AtomicInteger(1);
public void add(int c) {
count.addAndGet(c);
}
6、使用局部变量实现线程同步,如果使用ThreadLocal管理变量,则每一个使用该变量的线程都获得该变量的副本, 副本之间相互独立,这样每一个线程都可以随意修改自己的变量副本,而不会对其他线程产生影响。
ThreadLocal 类的常用方法
new ThreadLocalT() : 创建一个线程本地变量
get() : 返回此线程局部变量的当前线程副本中的值
initialValue() : 返回此线程局部变量的当前线程的"初始值"
set(T value) : 将此线程局部变量的当前线程副本中的值设置为value
示例代码:
private static ThreadLocalInteger count= new ThreadLocalInteger(){
@Override
protected Integer initialValue(){
return 1;
}
};
public void add(int c){
count.set(count.get() + c);
}
7、使用阻塞队列实现,例如LinkedBlockingQueue,具体使用可百度LinkedBlockingQueue的用法或查看java文档。
synchronized同步代码块,用于进行多线程同步使用,你所指的申明的对象,其实是线程锁,当一个线程执行到synchronized时,锁就被锁定,其他线程进不来,只能在外面等待,之所以不把锁对象省略是因为不同的需求需要不同的锁,必须两个线程用的是同一个类的两个实例对象呢,每一个对象的this是不同的两个对象,这个时候就锁不住了,所以这个时候应该用a.class
class a{
public void run{
synchronized (a.class){
System.out.println("xxxxx");
}
}