简单化问题
synchronized是对要执行的代码区进行同步锁定,不让多个线程对锁定的代码块同时调用,它需要锁对象。它的常用用法一般有两种,一种是对方法进行修饰,比如:public synchronized void test(String name) {......},另一种是关键区同步,形如synchronized (lock) {......}。对于方法同步来说说,其实相当于用this作为锁对象,也就是说下面这两种代码是相同的:
public
synchronized
void
test(String name, String lock)
...
{
//code
![](https://i-blog.csdnimg.cn/blog_migrate/6a9c071a08f1dae2d3e1c512000eef41.gif)
}
![](https://i-blog.csdnimg.cn/blog_migrate/6810355c2f78c12e91b7997a8e8c583a.gif)
![](https://i-blog.csdnimg.cn/blog_migrate/a41954a27d6ad96fa2c2cf816e677448.gif)
public
synchronized
void
test(String name, String lock)
...
{
![](https://i-blog.csdnimg.cn/blog_migrate/37c8bf68cdc3cc81759c34160776bc53.gif)
synchronized (this) ...{
//code
}
}
同步区能否按设计者的思路限定多线程访问,要注意是否使用同一把机锁。如下面的代码
public
class
Test
extends
Thread
...
{
private String name = null;
private static String lock = "lock";
![](https://i-blog.csdnimg.cn/blog_migrate/37c8bf68cdc3cc81759c34160776bc53.gif)
public Test(String ss) ...{
super();
this.name = ss;
}
![](https://i-blog.csdnimg.cn/blog_migrate/6a9c071a08f1dae2d3e1c512000eef41.gif)
private Single s = new Single();
![](https://i-blog.csdnimg.cn/blog_migrate/37c8bf68cdc3cc81759c34160776bc53.gif)
public void run()...{
![](https://i-blog.csdnimg.cn/blog_migrate/37c8bf68cdc3cc81759c34160776bc53.gif)
try ...{
![](https://i-blog.csdnimg.cn/blog_migrate/37c8bf68cdc3cc81759c34160776bc53.gif)
synchronized (this) ...{
System.out.println(name);
sleep(500);
System.out.println(name + ":after sleep 10000 s");
}
![](https://i-blog.csdnimg.cn/blog_migrate/6a9c071a08f1dae2d3e1c512000eef41.gif)
![](https://i-blog.csdnimg.cn/blog_migrate/37c8bf68cdc3cc81759c34160776bc53.gif)
} catch (Exception e) ...{
e.printStackTrace();
}
}
![](https://i-blog.csdnimg.cn/blog_migrate/6a9c071a08f1dae2d3e1c512000eef41.gif)
![](https://i-blog.csdnimg.cn/blog_migrate/37c8bf68cdc3cc81759c34160776bc53.gif)
public static void main(String[] args) throws Exception ...{
new Test("thread_1").start();
new Test("thread_2").start();
}
}
上面代码运行结果是
thread_1
thread_2
thread_1:after sleep 10000 s
thread_2:after sleep 10000 s
线程2并没等候线程1的机锁,因为机锁对象是不同的对象。如将synchronized (this)替换成synchronized (lock),那么运行结果就是我们期望的
thread_1
thread_1:after sleep 10000 s
thread_2
thread_2:after sleep 10000 s
static方法的synchronized
需要注意的是,static方法使用的机锁对象是className.class。
class
Test2
extends
Thread
...
{
![](https://i-blog.csdnimg.cn/blog_migrate/37c8bf68cdc3cc81759c34160776bc53.gif)
public static synchronized void mytest(String name)...{
System.out.println(name+" begin");
![](https://i-blog.csdnimg.cn/blog_migrate/37c8bf68cdc3cc81759c34160776bc53.gif)
try ...{
Thread.sleep(500);
![](https://i-blog.csdnimg.cn/blog_migrate/37c8bf68cdc3cc81759c34160776bc53.gif)
} catch (Exception e) ...{
}
System.out.println(name+" out");
}
![](https://i-blog.csdnimg.cn/blog_migrate/37c8bf68cdc3cc81759c34160776bc53.gif)
public void run()...{
mytest("Test2");
}
}
![](https://i-blog.csdnimg.cn/blog_migrate/6810355c2f78c12e91b7997a8e8c583a.gif)
![](https://i-blog.csdnimg.cn/blog_migrate/a41954a27d6ad96fa2c2cf816e677448.gif)
public
class
Test
extends
Thread
...
{
![](https://i-blog.csdnimg.cn/blog_migrate/37c8bf68cdc3cc81759c34160776bc53.gif)
public void run()...{
![](https://i-blog.csdnimg.cn/blog_migrate/37c8bf68cdc3cc81759c34160776bc53.gif)
synchronized (Test2.class) ...{//如果换成this或者其它机锁,则我们想要的同步机制就不起作用了
![](https://i-blog.csdnimg.cn/blog_migrate/37c8bf68cdc3cc81759c34160776bc53.gif)
try ...{
System.out.println("Test");
sleep(500);
System.out.println("Test:after sleep 10000 s");
![](https://i-blog.csdnimg.cn/blog_migrate/6a9c071a08f1dae2d3e1c512000eef41.gif)
![](https://i-blog.csdnimg.cn/blog_migrate/37c8bf68cdc3cc81759c34160776bc53.gif)
} catch (Exception e) ...{
e.printStackTrace();
}
}
}
![](https://i-blog.csdnimg.cn/blog_migrate/6a9c071a08f1dae2d3e1c512000eef41.gif)
![](https://i-blog.csdnimg.cn/blog_migrate/37c8bf68cdc3cc81759c34160776bc53.gif)
public static void main(String[] args) throws Exception ...{
new Test().start();
new Test2().start();
![](https://i-blog.csdnimg.cn/blog_migrate/37c8bf68cdc3cc81759c34160776bc53.gif)
/**//*执行结果是
Test
Test:after sleep 10000 s
Test2 begin
Test2 out
*/
}
}
sleep,suspend,resume,wait,notify,notifyall
sleep(static),suspend,resume同属Thread的方法,他们均不会释放机锁。不推荐使用。
wait,notify,notifyAll同属object的方法,会是否锁资源。我们只能对自己拥有的机锁调用wait,notify,如果调用不正确是可以编译通过,但运行时会报IllegalMonitorStateException。
public
void
run()
...
{
![](https://i-blog.csdnimg.cn/blog_migrate/37c8bf68cdc3cc81759c34160776bc53.gif)
synchronized (lock) ...{
![](https://i-blog.csdnimg.cn/blog_migrate/37c8bf68cdc3cc81759c34160776bc53.gif)
try ...{
System.out.println(name);
lock.wait();
System.out.println(name + ":after sleep 10000 s");
![](https://i-blog.csdnimg.cn/blog_migrate/6a9c071a08f1dae2d3e1c512000eef41.gif)
![](https://i-blog.csdnimg.cn/blog_migrate/37c8bf68cdc3cc81759c34160776bc53.gif)
} catch (Exception e) ...{
e.printStackTrace();
}
}
}
![](https://i-blog.csdnimg.cn/blog_migrate/6810355c2f78c12e91b7997a8e8c583a.gif)
![](https://i-blog.csdnimg.cn/blog_migrate/a41954a27d6ad96fa2c2cf816e677448.gif)
public
static
void
main(String[] args)
throws
Exception
...
{
Test t = new Test("thread_1");
t.start();
Thread.sleep(500);//保证下面的代码能唤醒线程
![](https://i-blog.csdnimg.cn/blog_migrate/37c8bf68cdc3cc81759c34160776bc53.gif)
synchronized (lock) ...{
lock.notifyAll();
}
}
想到的问题
我们在做web的action的时候,对某些比较耗性能的函数,常使用synchronized对方法进行限制,这需要注意如果acaction是单例模式,这种方法是可以的,但如果没有用单例模式,那么机锁对象action是不同的,也就没有达到设计者所想要的限制了。