Synchronized同步Quque队列Concurrency并发与线程锁Lock

GWA2 Java最近做了一次核心功能的升级,缺省模式下不再开启用于进行线程同步控制的synchronized功能。

在最近一次新项目的GWA2 Java开发部署中,我们需要调试一个通过WebApp.readObject来读取外部资源的功能。由于需求涉及到读取一个较长的资源列表,我们就设计了一个自动程序,循环轮询基于GWA2 Java的API接口。一切进展顺利,但程序偶尔会出现超时的现象。

起初我们怀疑是WebApp.readObject的方法中没有限制timeOut,导致读取外部资源时卡壳,进而影响到GWA2 Java应答外部需求。我们即对读取外部的URLConnection方法设置了 setConnectionTimeout和setReadTimeout两个限制时长的操作。这一改进也很快得到验证,部分请求确实会触发timeOut,根据需求适当延长这个限制即可。

然而问题仍然偶尔还会出现,尽管我们将轮询API的进程改为一个,轮询时间间隔如果稍微缩短一点,可能就会出现卡壳。问题一路narrow-down下来,就锁定在了程序执行上,当前一次的轮询没有完成,就触发下一次轮询时,下一次的轮询会天然地增加等待时长。相当于基于多线程、多进程的Apache+Tomcat变成了单线程服务。更为严重的表象时,当API应答程序在处理外部资源请求时,其他所有同一应用程序接口也一并被悬停,直至最后Timeout/504.

问题就不是当前API接口问题了,进一步的分析,我们将故障定位在此前某次某个项目的数据安全性核查时,发现没有数据共享/进程安全的设置,就在GWA2 Java的入口程序设置了Synchronized(this) 关键词约束——这样,整个Application应用将变得非常安全,只是性能上不再支持并发请求,所有请求必需单队列逐个处理。

通常在一般情况下,如此安全的设置和不支持并发请求并不会立即显现出来。这是因为GWA2 Java的应用开发交付后,多需要每个请求在数个毫秒级内处理完成,也即用户能感知到的2-3秒内,GWA2 Java应用程序已经顺序地完成了几十到几百个队列请求了。这几百个“同时”完成的请求,给终端用户甚至是开发者以支持“并发Concurrency”的假象。这样以来,某次更新GWA2 Java时,加入的 Synchronized的约束居然一直使用到现在,直到我们在测试育有超时的程序引发的GWA2 Java不能及时在毫秒级完成任务的特殊情况下,才触发我们进一步分析和完善这一潜在的漏洞(Bug)。

fig1.应用程序多线程下的线程锁

接着这个机会,我们想深入复习一下Synchronized同步Quque队列Concurrency并发与线程锁Lock。由于软件开发的主流逐渐步入以线程为单位,我们在网上找到一张描述线程间获取共享资源的流程示意图(如上图fig1.)。尽管这些名词有些抽象,我们可以拿一个具象的东西来说明这里的来龙去脉。比如高速公路上的收费站(如下图fig2.),收费服务就可以视为一个网络应用服务,每一个收费口就是一个应用服务的实例或进程,而每一个闸机口就一个处理线程。有一个闸机口的就是单线程,有多个闸机口的就是多线程。

fig.2高速公路收费口多通道并行

收费口的线程(闸机口)是多个并行,这很显然的是能够提升通行效率,而且线程同时开得线程越多,通行越快。这也是多进程多线程成为主流的关键之一。这是理想状态,也是默认的并行处理结果。因为每个闸机口在处理请求通行时,不需要彼此“问询”或者“交互”,各个可以独立自主地完成。用户计算机术语说是不不要处理“共享资源”,也不需要锁什么的。

如果我们人为的设置一个“共享资源”,情况会怎样?比如这所有的线程(闸机口)只有一把钥匙能开,每个线程完成计费、收费后通知这边钥匙去开闸放行。这就是典型的多线程秒变单线程了,完成收费后的线程需要等等开闸机的钥匙,然后再才能服务下一个请求。这个开闸机的“钥匙”就是fig1.中的“锁”。

只有一把钥匙的情况是虚拟的,现实生活中可能不存在。但核查车辆是否合法、司机是否违章是确实存在的需求,比如再多的闸机口都需要统一请求到交通中央数据库去比对车辆记录、司机记录,然后等待反馈结果。在世界的另一面,交通警察执法等在不停地向数据库中写入、更新违法、违章记录。当一笔写入发生时,所有的读取访问,都要被“悬停”等待,这就是“锁”。

由是可见,这同步与并发存在矛盾,为了减缓这种矛盾,收费口闸机口可能缓存交通中央数据库的数据,用一段时间再做一次更新,做到“准实时”(及时,in-time),而非“真实时”(准实,real-time). 在惊心动魄的逃亡类电影情节中我们偶尔能看到,男主女主苦主刚刚通过机场登机口闸机,边检员的屏幕上就显示出新推送到的苦主作为犯罪嫌疑人的资料。
在线网络服务中,用得较多的需要同步控制的“共享资源”的场景,如电商网站的库存,库存数据是每笔交易后都需要更新,当有更新发生时,必须进行枷锁操作,以使得当前有且仅有一个线程在操作数据,从而避免了“一货两卖”的错误。

同步、并发和锁的问题不独在Java中,在GWA2 PHP也会涉及到。所不同的是PHP的Synchronized的控制,既有系统地的PThread对象组件,也有微观flock方法函数。

只谈设计思想和实现思路,已经构成一篇博客Blog, 居然没有任何示例代码补贴出来。所幸无论是Java,还是PHP或者 GWA2 Perl, GWA2 Python等,都能够轻易地的通过搜索引擎找到编写良好的关于synchronization同步和Concurrency并发的示例代码。


GWA2

-GWA2 吉娃兔 是”通用网络应用架构( General Web Application Architeture, https://ufqi.com/dev/gwa2/ )”,基于 -GWA2 可以轻便构建各种网络应用程序,
包括复杂的在线购物商城、在线医疗、在线教育、 旅游交易平台、社群或者社交网站和新闻资讯网站等,
也包括各种企事业单位网上门户,在线交互及服务作业系统等.
还可以包括为NativeApp做服务器端支持, 甚至是WebApp的全部.
-GWA2 是为数不多的支持跨开发语言的应用框架,目前支持 -Java, -PHP, -Perl, -Aspx and -Python .

-GWA2 is a “General Web Application Architecture” and based on -GWA2 developers can easily build a variety of network applications,
including complex online shopping malls, online medical services, online teaching, travel trading platforms, community or social networking sites and news information sites, etc.
Also the applications include various online portals of enterprises and institutions, online interaction and service operations systems.
Moreover it contains server-side support for Native App, or even all of the WebApp.
-GWA2 is one of the web frameworks which provide cross-language support for -Java, -PHP, -Perl, -Aspx and -Python at present.

-GWA2 is E.A.S.Y 
Easy Along, Swift Yield
轻松启动, 快速产出.

本页地址: https://ufqi.com/blog/gwa2-php-synchronized/ , -R/T2ST

此条目发表在-GWA2, 编程技术, 计算机技术分类目录,贴了, , , , , 标签。将固定链接加入收藏夹。

Synchronized同步Quque队列Concurrency并发与线程锁Lock》有3条回应

  1. Pingback引用通告: GWA2 Java 增加多线程数据共享通道 globalData | -wordpress-wadelau

  2. Wadelau说:

    更新接续:
    GWA2 Java 增加多线程数据共享通道 globalData
    https://ufqi.com/blog/gwa2-java-multiple-threads-globaldata/

  3. Pingback引用通告: Synchronized同步Quque队列Concurrency并发与线程锁Lock | -wordpress-wadelau

发表评论

您的电子邮箱地址不会被公开。 必填项已用*标注

Captcha Code