JAVA线程中的安全知识

在JAVA中,线程与线程之间的数据是共享的,因此,当多个线程同时改变相同的对象,线程会相互倾轧。根据线程访问数据的不同线性,会产生被腐蚀的对象。

为了避免这种现象,我们需要对需要保护的对象上锁,这样在同一时间只能有一个线程访问这个数据,而其他的线程进入等待队列,知道这个线程访问完数据并释放锁,等待队列中的线程才能获得锁。

上锁的方法有多种,这里只写出常用的三种

1.synchronized代码块

synchronized (object)

{
}

例如:

 

public class TraditionalThreadSynchronized {
	public static void main(String[] args) {
		final Outputter output = new Outputter();
		new Thread() {
			public void run() {
				output.output("zhangsan");
			};
		}.start();		
		new Thread() {
			public void run() {
				output.output("lisi");
			};
		}.start();
	}
}
class Outputter {
	public void output(String name) {
		// TODO 为了保证对name的输出不是一个原子操作,这里逐个输出name的每个字符
synchronized (this)
{
		for(int i = 0; i < name.length(); i++) {
			System.out.print(name.charAt(i));
			// Thread.sleep(10);
		}
}

	}
}

 

 

object 必须是需要互斥的多个线程间的共享对象。

因此下面这段代码的锁是无效的

 

public class TraditionalThreadSynchronized {
	public static void main(String[] args) {
		final Outputter output = new Outputter();
		new Thread() {
			public void run() {
				output.output("zhangsan");
			};
		}.start();		
		new Thread() {
			public void run() {
				output.output("lisi");
			};
		}.start();
	}
}
class Outputter {
	public void output(String name) {
		// TODO 为了保证对name的输出不是一个原子操作,这里逐个输出name的每个字符
	Object object=new Object();
synchronizedobject)
{
for(int i = 0; i < name.length(); i++) {
			System.out.print(name.charAt(i));
			// Thread.sleep(10);
		}
}

		
	}
}

 

 

 

 

2.synchronized 方法

public synchronized void output(String name) {
    // TODO 线程输出方法
    for(int i = 0; i < name.length(); i++) {
        System.out.print(name.charAt(i));
    }
}

 这种方式就相当于用this锁住整个方法内的代码块,如果用synchronized加在静态方法上,就相当于用××××.class锁住整个方法内的代码块。使用synchronized在某些情况下会造成死锁,死锁问题以后会说明。使用synchronized修饰的方法或者代码块可以看成是一个原子操作

每个锁对都有两个队列,一个是就绪队列,一个是阻塞队列,就绪队列存储了将要获得锁的线程,阻塞队列存储了被阻塞的线 程,当一个线程被唤醒(notify)后,才会进入到就绪队列,等待CPU的调度,反之,当一个线程被wait后,就会进入阻塞队列,等待下一次被唤醒, 这个涉及到线程间的通信,一个线程执行互斥代码过程如下:

        1. 获得同步锁;

 

        2. 清空工作内存;

 

        3. 从主内存拷贝对象副本到工作内存;

 

        4. 执行代码(计算或者输出等);

 

        5. 刷新主内存数据;

 

        6. 释放同步锁。

        所以,synchronized既保证了多线程的并发有序性,又保证了多线程的内存可见性。

 

 

 

3.lock方法

Lock lc=new ReentrantLock();
lc.lock();

// do  work
lc.unlock();

这种方法一般不推荐使用

 

 

 

 

 

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值