Java线程(一):synchronized

一、什么时候会出现线程安全问题?

当多个线程同时访问一个资源(共享资源)时会出现线程安全。资源可以是一个变量、一个对象、一个文件、一个数据库表等。需要注意的是如果多个程序同时访问一个方法,定义在方法内部的局部变量并不是临界资源(共享资源),因为方法是在栈中执行的,而栈是线程私有的,因此不会出现线程安全问题。

二、如何解决线程安全问题?

通常来说在通过对访问共享资源代码加锁,当一个线程来访问时加锁,其他线程等待这个线程释放锁,当前线程执行完后加锁代码后释放锁资源。其他线程就可以访问共享资源了。在Java中,每一个对象都拥有一个锁标记(monitor),也称为监视器,多线程同时访问某个对象时,线程只有获取了该对象的锁才能访问。

    Java提供了两种方式来实现同步互斥访问:synchronized和Lock。

三、synchronized同步代码块和同步方法代码示例

package sync;

public class TestSynchronized {
	
	static TestSynchronized ts = new TestSynchronized();//所有线程共用这一个锁

	public static void main(String[] args) {
		new TestSynchronized().new Thread1().start();
		new TestSynchronized().new Thread2().start();
	}

	private void invoke() {
		try {
			synchronized (ts) {//同步代码块
				for (int i = 0; i < 5; i++) {
					System.out.println(Thread.currentThread().getName() + ":" + "写数据库" + i);
					Thread.sleep(100);
				}
			}
		} catch (InterruptedException e) {
			e.printStackTrace();
		}
	}
	
	class Thread1 extends Thread{
		public void run(){
			ts.invoke();
		}
	}
	
	class Thread2 extends Thread{
		public void run(){
			ts.invoke();
		}
	}
}



运行结果: Thread-0和Thread-1依次执行,没有出现相互竞争执行。

Thread-0:写数据库0
Thread-0:写数据库1
Thread-0:写数据库2
Thread-0:写数据库3
Thread-0:写数据库4
Thread-1:写数据库0
Thread-1:写数据库1
Thread-1:写数据库2
Thread-1:写数据库3
Thread-1:写数据库4

如果将锁加在方法上执行,结果依然一样:

	private synchronized void invoke() {
		try {
			for (int i = 0; i < 5; i++) {
				System.out.println(Thread.currentThread().getName() + ":" + "写数据库" + i);
				Thread.sleep(100);
			}
		} catch (InterruptedException e) {
			e.printStackTrace();
		}
	}
运行结果:
Thread-0:写数据库0
Thread-0:写数据库1
Thread-0:写数据库2
Thread-0:写数据库3
Thread-0:写数据库4
Thread-1:写数据库0
Thread-1:写数据库1
Thread-1:写数据库2
Thread-1:写数据库3
Thread-1:写数据库4

四、同步方法和同步代码块的区别。

synchronized代码块使用起来比synchronized方法要灵活得多。因为也许一个方法中只有一部分代码只需要同步,如果此时对整个方法用synchronized进行同步,会影响程序执行效率。而使用synchronized代码块就可以避免这个问题,synchronized代码块可以实现只对需要同步的地方进行同步。

五、synchronized需要注意的几点。

1)当一个线程访问一个对象的synchronized方法func1其他线程不能访问这个对象方法func1,因为一个对象只有一个锁。只有释放了锁才能访问func1。

2)当一个线程访问一个对象的synchronized方法func1其他线程可以访问这个对象的非synchronized方法,因为其他方法不需要该对象的锁。

3)如果一个类有static synchronized方法f1和synchronized方法f2,当两个线程分别访问f1和f2时是不会发生互斥的问题,因为一个是对象锁一个是类锁,不是同一个锁。

4)如果synchronized方法或者synchronized代码块发生异常,是不会出现由于异常导致死锁,因为发生异常后JVM会释放锁,这个Lock不一样,lock需要手动释放锁。


  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值